From bb6abf1890c502e0af575d3a50741d98beb47c4b Mon Sep 17 00:00:00 2001 From: sauravniraula Date: Thu, 31 Jul 2025 15:50:41 +0545 Subject: [PATCH] feat(fastapi): converts schema to pydantic model for structured response, fix: changes icon and image schema for pydantic model support --- .dockerignore | 3 +- .gitignore | 3 +- .../api/v1/ppt/endpoints/presentation.py | 24 ++++- servers/fastapi/api/v1/ppt/endpoints/slide.py | 18 +++- servers/fastapi/chroma/chroma.sqlite3 | Bin 4329472 -> 4329472 bytes servers/fastapi/get_test_schema.py | 4 +- servers/fastapi/models/presentation_layout.py | 2 +- servers/fastapi/requirements.txt | 12 +++ servers/fastapi/services/__init__.py | 2 + servers/fastapi/services/llm_client.py | 11 +-- .../services/schema_to_model_service.py | 93 +++++++++++++----- servers/fastapi/utils/llm_calls/edit_slide.py | 8 +- .../generate_presentation_structure.py | 2 +- .../utils/llm_calls/generate_slide_content.py | 27 ++--- .../llm_calls/select_slide_type_on_edit.py | 4 +- servers/fastapi/utils/llm_provider.py | 2 +- servers/fastapi/utils/process_slides.py | 50 +++++----- .../components/EditableLayoutWrapper.tsx | 14 +-- .../ExampleSlideLayout.tsx | 18 ++-- .../classic/Type10SlideLayout.tsx | 14 +-- .../classic/Type1SlideLayout.tsx | 8 +- .../classic/Type3SlideLayout.tsx | 16 +-- .../classic/Type6SlideLayout.tsx | 20 ++-- .../classic/Type7SlideLayout.tsx | 30 +++--- .../classic/Type8SlideLayout.tsx | 28 +++--- .../presentation-layouts/defaultSchemes.ts | 8 +- .../general/BasicInfoSlideLayout.tsx | 8 +- .../general/BulletIconsOnlySlideLayout.tsx | 28 +++--- .../general/BulletWithIconsSlideLayout.tsx | 20 ++-- .../general/ChartWithBulletsSlideLayout.tsx | 16 +-- .../general/IntroSlideLayout.tsx | 8 +- .../general/MetricsWithImageSlideLayout.tsx | 8 +- .../general/NumberedBulletsSlideLayout.tsx | 8 +- .../general/QuoteSlideLayout.tsx | 6 +- .../general/TeamSlideLayout.tsx | 20 ++-- .../modern/2AboutCompanySlideLayout.tsx | 4 +- .../modern/3ProblemSlideLayout.tsx | 22 ++--- .../modern/4SolutionSlideLayout.tsx | 22 ++--- .../modern/5ProductOverviewSlideLayout.tsx | 16 +-- .../modern/6MarketSizeSlideLayout.tsx | 8 +- .../modern/z10TeamSlideLayout.tsx | 22 ++--- .../professional/AboutUsSlide.tsx | 10 +- .../professional/BusinessModelSlide.tsx | 10 +- .../professional/MarketSizeSlide.tsx | 10 +- .../professional/OurServiceSlide.tsx | 10 +- .../professional/ProblemsSlide.tsx | 10 +- .../professional/SolutionsSlide.tsx | 20 ++-- .../professional/StatisticCircularSlide.tsx | 14 +-- .../professional/StatisticDualChartSlide.tsx | 10 +- .../professional/StatisticSlide.tsx | 10 +- .../professional/TableOfContentsSlide.tsx | 10 +- .../professional/TestimonialSlide.tsx | 28 +++--- .../professional/ThankYouSlide.tsx | 10 +- .../professional/TitleSlide.tsx | 10 +- .../professional/WhatWeBelieveSlide.tsx | 10 +- .../store/slices/presentationGeneration.ts | 8 +- 56 files changed, 440 insertions(+), 377 deletions(-) diff --git a/.dockerignore b/.dockerignore index 164cf77b..dcf9035b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,4 +8,5 @@ build .gitignore tmp debug -.fastembed_cache \ No newline at end of file +.fastembed_cache +generated_models \ No newline at end of file diff --git a/.gitignore b/.gitignore index 81923a11..33c06363 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ app_data tmp debug .fastembed_cache -my-doc.txt \ No newline at end of file +my-doc.txt +generated_models \ No newline at end of file diff --git a/servers/fastapi/api/v1/ppt/endpoints/presentation.py b/servers/fastapi/api/v1/ppt/endpoints/presentation.py index 6b9cecc7..31207b95 100644 --- a/servers/fastapi/api/v1/ppt/endpoints/presentation.py +++ b/servers/fastapi/api/v1/ppt/endpoints/presentation.py @@ -2,10 +2,11 @@ import asyncio import json import os import random +import importlib from typing import Annotated, List, Literal, Optional from fastapi import APIRouter, Body, Depends, File, HTTPException, UploadFile from fastapi.responses import StreamingResponse -from sqlalchemy import String, cast, delete +from sqlalchemy import delete from sqlalchemy.ext.asyncio import AsyncSession from sqlmodel import select from constants.documents import UPLOAD_ACCEPTED_FILE_TYPES @@ -27,7 +28,7 @@ from utils.export_utils import export_presentation from utils.llm_calls.generate_presentation_outlines import generate_ppt_outline from models.sql.slide import SlideModel from models.sse_response import SSECompleteResponse, SSEResponse -from services import TEMP_FILE_SERVICE +from services import SCHEMA_TO_MODEL_SERVICE, TEMP_FILE_SERVICE from services.database import get_async_session from services.documents_loader import DocumentsLoader from models.sql.presentation import PresentationModel @@ -42,6 +43,7 @@ from utils.llm_calls.generate_slide_content import ( ) from utils.process_slides import process_slide_and_fetch_assets from utils.randomizers import get_random_uuid +from utils.schema_utils import remove_fields_from_schema from utils.validators import validate_files PRESENTATION_ROUTER = APIRouter(prefix="/presentation", tags=["Presentation"]) @@ -217,9 +219,23 @@ async def stream_presentation( ).to_string() for i, slide_layout_index in enumerate(structure.slides): slide_layout = layout.slides[slide_layout_index] - slide_content = await get_slide_content_from_type_and_outline( - slide_layout, outline.slides[i], presentation.language + + # Generate Pydantic model from slide layout schema + schema_model_id = f"{layout.name}/{slide_layout.id}" + response_schema = remove_fields_from_schema( + slide_layout.json_schema, ["image_url_", "icon_url_"] ) + schema_model_path = ( + await SCHEMA_TO_MODEL_SERVICE.get_pydantic_model_path_from_schema( + schema_model_id, response_schema + ) + ) + module = importlib.import_module(schema_model_path) + response_model = module.GeneratedModel + slide_content = await get_slide_content_from_type_and_outline( + response_model, outline.slides[i], presentation.language + ) + slide = SlideModel( presentation=presentation_id, layout_group=layout.name, diff --git a/servers/fastapi/api/v1/ppt/endpoints/slide.py b/servers/fastapi/api/v1/ppt/endpoints/slide.py index 3a254453..3e0dfcce 100644 --- a/servers/fastapi/api/v1/ppt/endpoints/slide.py +++ b/servers/fastapi/api/v1/ppt/endpoints/slide.py @@ -1,9 +1,11 @@ +import importlib from typing import Annotated, Optional from fastapi import APIRouter, Body, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from models.sql.presentation import PresentationModel from models.sql.slide import SlideModel +from services import SCHEMA_TO_MODEL_SERVICE from services.database import get_async_session from services.icon_finder_service import IconFinderService from services.image_generation_service import ImageGenerationService @@ -13,6 +15,7 @@ from utils.llm_calls.edit_slide_html import get_edited_slide_html from utils.llm_calls.select_slide_type_on_edit import get_slide_layout_from_prompt from utils.process_slides import process_old_and_new_slides_and_fetch_assets from utils.randomizers import get_random_uuid +from utils.schema_utils import remove_fields_from_schema SLIDE_ROUTER = APIRouter(prefix="/slide", tags=["Slide"]) @@ -36,8 +39,21 @@ async def edit_slide( slide_layout = await get_slide_layout_from_prompt( prompt, presentation_layout, slide ) + + # Generate Pydantic model from slide layout schema + schema_model_id = f"{presentation_layout.name}/{slide_layout.id}" + response_schema = remove_fields_from_schema( + slide_layout.json_schema, ["image_url_", "icon_url_"] + ) + schema_model_path = ( + await SCHEMA_TO_MODEL_SERVICE.get_pydantic_model_path_from_schema( + schema_model_id, response_schema + ) + ) + module = importlib.import_module(schema_model_path) + response_model = module.GeneratedModel edited_slide_content = await get_edited_slide_content( - prompt, slide_layout, slide, presentation.language + prompt, slide, presentation.language, response_model ) image_generation_service = ImageGenerationService(get_images_directory()) diff --git a/servers/fastapi/chroma/chroma.sqlite3 b/servers/fastapi/chroma/chroma.sqlite3 index c35454c7e39142dab91db807cb46c2a859c5b2f7..7398b74cc10375549177da21755a7172566ee0f7 100644 GIT binary patch delta 462 zcmW;HIZnf16h+}U4nrUq!jQ?%=**KdnHhc%8%Y~BK_rBrgaWyxU;~JPZLkD(LCd)m z-_et9^_Fi>@g<&J%e;6umid^!2Z_-6jlHJ)+t2jRgL7wxb}VVnl&LaN#>z+ul%Xque)n@C{`4z{s_G5{xjx3=6EV!43zUaKQ}^ypZ989{~grLKqQ5 z5knjaB#}ZI87Rmihdc@>qJ%OksG^2C8fc=0HdJ)bMGt)pFvJLBOfba^b1bmL3jh21 JEws(y^8<42ZkYf8 diff --git a/servers/fastapi/get_test_schema.py b/servers/fastapi/get_test_schema.py index 0ae458b3..f03966d4 100644 --- a/servers/fastapi/get_test_schema.py +++ b/servers/fastapi/get_test_schema.py @@ -17,8 +17,8 @@ class ContactInfoModel(BaseModel): class ImageModel(BaseModel): - __image_url__: str = Field(description="Image URL") - __image_prompt__: str = Field(description="Image prompt") + image_url_: str = Field(description="Image URL") + image_prompt_: str = Field(description="Image prompt") # First Slide Layout diff --git a/servers/fastapi/models/presentation_layout.py b/servers/fastapi/models/presentation_layout.py index 5e90dc85..fe462554 100644 --- a/servers/fastapi/models/presentation_layout.py +++ b/servers/fastapi/models/presentation_layout.py @@ -12,7 +12,7 @@ class SlideLayoutModel(BaseModel): class PresentationLayoutModel(BaseModel): - name: Optional[str] = None + name: str ordered: bool = Field(default=False) slides: List[SlideLayoutModel] diff --git a/servers/fastapi/requirements.txt b/servers/fastapi/requirements.txt index 685964dd..75a5b248 100644 --- a/servers/fastapi/requirements.txt +++ b/servers/fastapi/requirements.txt @@ -6,11 +6,13 @@ aiosqlite==0.21.0 annotated-types==0.7.0 anthropic==0.60.0 anyio==4.9.0 +argcomplete==3.6.2 async-timeout==5.0.1 asyncpg==0.30.0 attrs==25.3.0 backoff==2.2.1 bcrypt==4.3.0 +black==25.1.0 build==1.2.2.post1 cachetools==5.5.2 certifi==2025.7.14 @@ -20,6 +22,7 @@ chromadb==1.0.15 click==8.2.1 coloredlogs==15.0.1 cryptography==45.0.5 +datamodel-code-generator==0.32.0 distro==1.9.0 dnspython==2.7.0 durationpy==0.10 @@ -32,6 +35,7 @@ filelock==3.18.0 flatbuffers==25.2.10 frozenlist==1.7.0 fsspec==2025.7.0 +genson==1.3.0 google-auth==2.40.3 google-genai==1.25.0 googleapis-common-protos==1.70.0 @@ -50,7 +54,9 @@ hyperframe==6.1.0 idna==3.10 importlib_metadata==8.7.0 importlib_resources==6.5.2 +inflect==7.5.0 iniconfig==2.1.0 +isort==6.0.1 Jinja2==3.1.6 jiter==0.10.0 jsonschema==4.25.0 @@ -62,8 +68,10 @@ markdown-it-py==3.0.0 MarkupSafe==3.0.2 mdurl==0.1.2 mmh3==5.1.0 +more-itertools==10.7.0 mpmath==1.3.0 multidict==6.6.3 +mypy_extensions==1.1.0 numpy==2.3.2 oauthlib==3.3.1 onnxruntime==1.22.1 @@ -77,10 +85,12 @@ opentelemetry-semantic-conventions==0.56b0 orjson==3.11.1 overrides==7.7.0 packaging==25.0 +pathspec==0.12.1 pathvalidate==3.3.1 pdfminer.six==20250506 pdfplumber==0.11.7 pillow==11.3.0 +platformdirs==4.3.8 pluggy==1.6.0 portalocker==3.2.0 posthog==5.4.0 @@ -123,7 +133,9 @@ starlette==0.47.1 sympy==1.14.0 tenacity==8.5.0 tokenizers==0.21.2 +tomli==2.2.1 tqdm==4.67.1 +typeguard==4.4.4 typer==0.16.0 typing-inspection==0.4.1 typing_extensions==4.14.1 diff --git a/servers/fastapi/services/__init__.py b/servers/fastapi/services/__init__.py index 2c4366c5..bcf11e3c 100644 --- a/servers/fastapi/services/__init__.py +++ b/servers/fastapi/services/__init__.py @@ -1,6 +1,8 @@ from services.redis_service import RedisService +from services.schema_to_model_service import SchemaToModelService from services.temp_file_service import TempFileService TEMP_FILE_SERVICE = TempFileService() REDIS_SERVICE = RedisService() +SCHEMA_TO_MODEL_SERVICE = SchemaToModelService(TEMP_FILE_SERVICE) diff --git a/servers/fastapi/services/llm_client.py b/servers/fastapi/services/llm_client.py index af5b0e9d..4184b18e 100644 --- a/servers/fastapi/services/llm_client.py +++ b/servers/fastapi/services/llm_client.py @@ -205,14 +205,13 @@ class LLMClient: ) content = response.choices[0].message.parsed if content: - return content + return content.model_dump(mode="json") return None async def _generate_google_structured( self, model: str, messages: List[LLMMessage], response_format: BaseModel | dict ): client: genai.Client = self._client - is_response_format_dict = isinstance(response_format, dict) response = await asyncio.to_thread( client.models.generate_content, model=model, @@ -228,9 +227,6 @@ class LLMClient: if response.text: content = json.loads(response.text) - # If response format is Pydantic model, return the model instance - if content and not is_response_format_dict: - return response_format(**content) return content async def _generate_anthropic_structured( @@ -263,9 +259,6 @@ class LLMClient: if content_block.type == "tool_use": content = content_block.input - # If response format is Pydantic model, return the model instance - if content and not is_response_format_dict: - return response_format(**content) return content async def _generate_ollama_structured( @@ -280,7 +273,7 @@ class LLMClient: async def generate_structured( self, model: str, messages: List[LLMMessage], response_format: BaseModel | dict - ): + ) -> dict: content = None match self.llm_provider: case LLMProvider.OPENAI: diff --git a/servers/fastapi/services/schema_to_model_service.py b/servers/fastapi/services/schema_to_model_service.py index 94ce110c..655329bc 100644 --- a/servers/fastapi/services/schema_to_model_service.py +++ b/servers/fastapi/services/schema_to_model_service.py @@ -1,39 +1,78 @@ +import asyncio import json -import tempfile -from pydantic import BaseModel +import os +from pathlib import Path +from typing import Dict +from fastapi import HTTPException +from datamodel_code_generator import generate, InputFileType, DataModelType -from services import TEMP_FILE_SERVICE +from services.temp_file_service import TempFileService from utils.randomizers import get_random_uuid class SchemaToModelService: - def __init__(self): - self.temp_dir = TEMP_FILE_SERVICE.create_temp_dir() - self._records = {} + def __init__(self, temp_file_service: TempFileService): + self.temp_file_service = temp_file_service + self.temp_dir = self.temp_file_service.create_temp_dir() - def convert(self, schema: dict, identifier: str) -> BaseModel: - return BaseModel.model_validate(schema) + self.generated_models_dir = "generated_models" + if os.path.exists(self.generated_models_dir): + for file in os.listdir(self.generated_models_dir): + if file.endswith(".py"): + os.remove(os.path.join(self.generated_models_dir, file)) + os.makedirs(self.generated_models_dir, exist_ok=True) - def schema_to_pydantic_model(self, schema: dict, class_name: str): - schema_path = TEMP_FILE_SERVICE.create_temp_file_path( - get_random_uuid() + ".json", self.temp_dir + self._records: Dict[str, str] = {} + self._fetch_locks: Dict[str, asyncio.Lock] = {} + + def convert_path_to_module_path(self, path: str): + return path.replace("/", ".").replace("\\", ".").replace(".py", "") + + async def get_pydantic_model_path_from_schema( + self, identifier: str, schema: dict + ) -> str: + if identifier in self._fetch_locks: + async with self._fetch_locks[identifier]: + return self._records[identifier] + else: + async_lock = asyncio.Lock() + await async_lock.acquire() + self._fetch_locks[identifier] = async_lock + model_path = await self.generate_pydantic_model_from_schema_async(schema) + model_path = self.convert_path_to_module_path(model_path) + self._records[identifier] = model_path + async_lock.release() + return model_path + + async def generate_pydantic_model_from_schema_async(self, schema: dict): + return await asyncio.to_thread(self.generate_pydantic_model_from_schema, schema) + + def generate_pydantic_model_from_schema(self, schema: dict): + generated_model_path = os.path.join( + self.generated_models_dir, get_random_uuid() + ".py" ) - with open(schema_path, "w") as f: - json.dump(schema, f) + try: + schema_path = self.temp_file_service.create_temp_file_path( + get_random_uuid() + ".json", self.temp_dir + ) + with open(schema_path, "w") as f: + json.dump(schema, f) - generated_model_path = TEMP_FILE_SERVICE.create_temp_file_path( - get_random_uuid() + ".py", self.temp_dir - ) - # generate( - # input_=Path(schema_path), - # input_file_type=InputFileType.JsonSchema, - # output=Path(output_file), - # output_model_type=DataModelType.PydanticV2BaseModel, - # class_name=class_name, - # use_annotated=False, - # field_constraints=True, - # ) - - # Path(schema_file).unlink(missing_ok=True) + generate( + input_=Path(schema_path), + input_file_type=InputFileType.JsonSchema, + output=Path(generated_model_path), + output_model_type=DataModelType.PydanticV2BaseModel, + class_name="GeneratedModel", + use_annotated=False, + field_constraints=True, + extra_fields="ignore", + ) + except Exception as e: + raise HTTPException( + status_code=500, detail="Failed to generate Pydantic model from schema" + ) + finally: + self.temp_file_service.cleanup_temp_file(schema_path) return generated_model_path diff --git a/servers/fastapi/utils/llm_calls/edit_slide.py b/servers/fastapi/utils/llm_calls/edit_slide.py index 1ffb0e0c..f572779b 100644 --- a/servers/fastapi/utils/llm_calls/edit_slide.py +++ b/servers/fastapi/utils/llm_calls/edit_slide.py @@ -1,3 +1,4 @@ +from pydantic import BaseModel from models.llm_message import LLMMessage from models.presentation_layout import SlideLayoutModel from models.sql.slide import SlideModel @@ -54,19 +55,16 @@ def get_messages( async def get_edited_slide_content( prompt: str, - slide_layout: SlideLayoutModel, slide: SlideModel, language: str, + response_model: BaseModel, ): model = get_large_model() - response_schema = remove_fields_from_schema( - slide_layout.json_schema, ["__image_url__", "__icon_url__"] - ) client = LLMClient() response = await client.generate_structured( model=model, messages=get_messages(prompt, slide.content, language), - response_format=response_schema, + response_format=response_model, ) return response diff --git a/servers/fastapi/utils/llm_calls/generate_presentation_structure.py b/servers/fastapi/utils/llm_calls/generate_presentation_structure.py index 26c2c188..056dd418 100644 --- a/servers/fastapi/utils/llm_calls/generate_presentation_structure.py +++ b/servers/fastapi/utils/llm_calls/generate_presentation_structure.py @@ -76,4 +76,4 @@ async def generate_presentation_structure( ), response_format=response_model, ) - return response + return PresentationStructureModel(**response) diff --git a/servers/fastapi/utils/llm_calls/generate_slide_content.py b/servers/fastapi/utils/llm_calls/generate_slide_content.py index 5d6a9b5b..e69f02e0 100644 --- a/servers/fastapi/utils/llm_calls/generate_slide_content.py +++ b/servers/fastapi/utils/llm_calls/generate_slide_content.py @@ -1,19 +1,8 @@ -import asyncio -import json -from google.genai.types import GenerateContentConfig +from pydantic import BaseModel from models.llm_message import LLMMessage -from models.presentation_layout import SlideLayoutModel from models.presentation_outline_model import SlideOutlineModel from services.llm_client import LLMClient -from utils.llm_provider import ( - get_anthropic_llm_client, - get_google_llm_client, - get_large_model, - get_llm_client, - is_anthropic_selected, - is_google_selected, -) -from utils.schema_utils import remove_fields_from_schema +from utils.llm_provider import get_large_model system_prompt = """ Generate structured slide based on provided title and outline, follow mentioned steps and notes and provide structured output. @@ -25,8 +14,8 @@ system_prompt = """ # Notes - Slide body should not use words like "This slide", "This presentation". - Rephrase the slide body to make it flow naturally. - - Provide prompt to generate image on "__image_prompt__" property. - - Provide query to search icon on "__icon_query__" property. + - Provide prompt to generate image on "image_prompt_" property. + - Provide query to search icon on "icon_query_" property. - Do not use markdown formatting in slide body. - Make sure to follow language guidelines. **Strictly follow the max and min character limit for every property in the slide.** @@ -64,15 +53,11 @@ def get_messages(title: str, outline: str, language: str): async def get_slide_content_from_type_and_outline( - slide_layout: SlideLayoutModel, outline: SlideOutlineModel, language: str + response_model: BaseModel, outline: SlideOutlineModel, language: str ): client = LLMClient() model = get_large_model() - response_schema = remove_fields_from_schema( - slide_layout.json_schema, ["__image_url__", "__icon_url__"] - ) - response = await client.generate_structured( model=model, messages=get_messages( @@ -80,6 +65,6 @@ async def get_slide_content_from_type_and_outline( outline.body, language, ), - response_format=response_schema, + response_format=response_model, ) return response diff --git a/servers/fastapi/utils/llm_calls/select_slide_type_on_edit.py b/servers/fastapi/utils/llm_calls/select_slide_type_on_edit.py index 4ed1ffd7..a41c717b 100644 --- a/servers/fastapi/utils/llm_calls/select_slide_type_on_edit.py +++ b/servers/fastapi/utils/llm_calls/select_slide_type_on_edit.py @@ -48,7 +48,7 @@ async def get_slide_layout_from_prompt( slide_layout_ids = list(map(lambda x: x.id, layout.slides)) - response: SlideLayoutIndex = await client.generate_structured( + response = await client.generate_structured( model=model, messages=get_messages( prompt, @@ -58,5 +58,5 @@ async def get_slide_layout_from_prompt( ), response_format=SlideLayoutIndex, ) - index = response.index + index = SlideLayoutIndex(**response).index return layout.slides[index] diff --git a/servers/fastapi/utils/llm_provider.py b/servers/fastapi/utils/llm_provider.py index f314f2b3..23e98f62 100644 --- a/servers/fastapi/utils/llm_provider.py +++ b/servers/fastapi/utils/llm_provider.py @@ -107,7 +107,7 @@ def get_anthropic_llm_client(): def get_large_model(): selected_llm = get_llm_provider() if selected_llm == LLMProvider.OPENAI: - return "gpt-4.1-nano" + return "gpt-4.1" elif selected_llm == LLMProvider.GOOGLE: return "gemini-2.0-flash" elif selected_llm == LLMProvider.ANTHROPIC: diff --git a/servers/fastapi/utils/process_slides.py b/servers/fastapi/utils/process_slides.py index 6ffca66f..2623f95f 100644 --- a/servers/fastapi/utils/process_slides.py +++ b/servers/fastapi/utils/process_slides.py @@ -17,15 +17,15 @@ async def process_slide_and_fetch_assets( async_tasks = [] - image_paths = get_dict_paths_with_key(slide.content, "__image_prompt__") - icon_paths = get_dict_paths_with_key(slide.content, "__icon_query__") + image_paths = get_dict_paths_with_key(slide.content, "image_prompt_") + icon_paths = get_dict_paths_with_key(slide.content, "icon_query_") for image_path in image_paths: image_prompt_parent = get_dict_at_path(slide.content, image_path) async_tasks.append( image_generation_service.generate_image( ImagePrompt( - prompt=image_prompt_parent["__image_prompt__"], + prompt=image_prompt_parent["image_prompt_"], ) ) ) @@ -33,7 +33,7 @@ async def process_slide_and_fetch_assets( for icon_path in icon_paths: icon_query_parent = get_dict_at_path(slide.content, icon_path) async_tasks.append( - icon_finder_service.search_icons(icon_query_parent["__icon_query__"]) + icon_finder_service.search_icons(icon_query_parent["icon_query_"]) ) results = await asyncio.gather(*async_tasks) @@ -45,14 +45,14 @@ async def process_slide_and_fetch_assets( result = results.pop() if isinstance(result, ImageAsset): return_assets.append(result) - image_dict["__image_url__"] = result.path + image_dict["image_url_"] = result.path else: - image_dict["__image_url__"] = result + image_dict["image_url_"] = result set_dict_at_path(slide.content, image_path, image_dict) for icon_path in icon_paths: icon_dict = get_dict_at_path(slide.content, icon_path) - icon_dict["__icon_url__"] = results.pop()[0] + icon_dict["icon_url_"] = results.pop()[0] set_dict_at_path(slide.content, icon_path, icon_dict) return return_assets @@ -66,34 +66,34 @@ async def process_old_and_new_slides_and_fetch_assets( ) -> List[ImageAsset]: # Finds all old images old_image_dict_paths = get_dict_paths_with_key( - old_slide_content, "__image_prompt__" + old_slide_content, "image_prompt_" ) old_image_dicts = [ get_dict_at_path(old_slide_content, path) for path in old_image_dict_paths ] old_image_prompts = [ - old_image_dict["__image_prompt__"] for old_image_dict in old_image_dicts + old_image_dict["image_prompt_"] for old_image_dict in old_image_dicts ] # Finds all old icons - old_icon_dict_paths = get_dict_paths_with_key(old_slide_content, "__icon_query__") + old_icon_dict_paths = get_dict_paths_with_key(old_slide_content, "icon_query_") old_icon_dicts = [ get_dict_at_path(old_slide_content, path) for path in old_icon_dict_paths ] old_icon_queries = [ - old_icon_dict["__icon_query__"] for old_icon_dict in old_icon_dicts + old_icon_dict["icon_query_"] for old_icon_dict in old_icon_dicts ] # Finds all new images new_image_dict_paths = get_dict_paths_with_key( - new_slide_content, "__image_prompt__" + new_slide_content, "image_prompt_" ) new_image_dicts = [ get_dict_at_path(new_slide_content, path) for path in new_image_dict_paths ] # Finds all new icons - new_icon_dict_paths = get_dict_paths_with_key(new_slide_content, "__icon_query__") + new_icon_dict_paths = get_dict_paths_with_key(new_slide_content, "icon_query_") new_icon_dicts = [ get_dict_at_path(new_slide_content, path) for path in new_icon_dict_paths ] @@ -109,18 +109,18 @@ async def process_old_and_new_slides_and_fetch_assets( # Creates async tasks for fetching new images # Use old image url if prompt is same for new_image in new_image_dicts: - if new_image["__image_prompt__"] in old_image_prompts: + if new_image["image_prompt_"] in old_image_prompts: old_image_url = old_image_dicts[ - old_image_prompts.index(new_image["__image_prompt__"]) - ]["__image_url__"] - new_image["__image_url__"] = old_image_url + old_image_prompts.index(new_image["image_prompt_"]) + ]["image_url_"] + new_image["image_url_"] = old_image_url new_images_fetch_status.append(False) continue async_image_fetch_tasks.append( image_generation_service.generate_image( ImagePrompt( - prompt=new_image["__image_prompt__"], + prompt=new_image["image_prompt_"], ) ) ) @@ -129,16 +129,16 @@ async def process_old_and_new_slides_and_fetch_assets( # Creates async tasks for fetching new icons # Use old icon url if query is same for new_icon in new_icon_dicts: - if new_icon["__icon_query__"] in old_icon_queries: + if new_icon["icon_query_"] in old_icon_queries: old_icon_url = old_icon_dicts[ - old_icon_queries.index(new_icon["__icon_query__"]) - ]["__icon_url__"] - new_icon["__icon_url__"] = old_icon_url + old_icon_queries.index(new_icon["icon_query_"]) + ]["icon_url_"] + new_icon["icon_url_"] = old_icon_url new_icons_fetch_status.append(False) continue async_icon_fetch_tasks.append( - icon_finder_service.search_icons(new_icon["__icon_query__"]) + icon_finder_service.search_icons(new_icon["icon_query_"]) ) new_icons_fetch_status.append(True) @@ -157,11 +157,11 @@ async def process_old_and_new_slides_and_fetch_assets( image_url = fetched_image.path else: image_url = fetched_image - new_image_dicts[i]["__image_url__"] = image_url + new_image_dicts[i]["image_url_"] = image_url for i, new_icon in enumerate(new_icons): if new_icons_fetch_status[i]: - new_icon_dicts[i]["__icon_url__"] = new_icons[i][0] + new_icon_dicts[i]["icon_url_"] = new_icons[i][0] for i, new_image_dict in enumerate(new_image_dicts): set_dict_at_path(new_slide_content, new_image_dict_paths[i], new_image_dict) diff --git a/servers/nextjs/app/(presentation-generator)/components/EditableLayoutWrapper.tsx b/servers/nextjs/app/(presentation-generator)/components/EditableLayoutWrapper.tsx index 4ecd8257..3a0969bc 100644 --- a/servers/nextjs/app/(presentation-generator)/components/EditableLayoutWrapper.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/EditableLayoutWrapper.tsx @@ -42,12 +42,12 @@ const EditableLayoutWrapper: React.FC = ({ const matches: { path: string; type: 'image' | 'icon'; data: any }[] = []; - // Check current level for __image_url__ or __icon_url__ - if (data.__image_url__ && targetUrl.includes(data.__image_url__)) { + // Check current level for image_url_ or icon_url_ + if (data.image_url_ && targetUrl.includes(data.image_url_)) { matches.push({ path, type: 'image', data }); } - if (data.__icon_url__ && targetUrl.includes(data.__icon_url__)) { + if (data.icon_url_ && targetUrl.includes(data.icon_url_)) { matches.push({ path, type: 'icon', data }); } @@ -308,7 +308,7 @@ const EditableLayoutWrapper: React.FC = ({ slideIndex, dataPath: activeEditor.dataPath, imageUrl: newImageUrl, - prompt: prompt || activeEditor.data?.__image_prompt__ || '' + prompt: prompt || activeEditor.data?.image_prompt_ || '' })); setActiveEditor(null); } @@ -326,7 +326,7 @@ const EditableLayoutWrapper: React.FC = ({ slideIndex, dataPath: activeEditor.dataPath, iconUrl: newIconUrl, - query: query || activeEditor.data?.__icon_query__ || '' + query: query || activeEditor.data?.icon_query_ || '' })); @@ -361,7 +361,7 @@ const EditableLayoutWrapper: React.FC = ({ = ({ {/* Render IconsEditor when an icon is being edited */} {activeEditor && activeEditor.type === 'icon' && ( diff --git a/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx b/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx index 583d6524..a3a68392 100644 --- a/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/ExampleSlideLayout.tsx @@ -31,15 +31,15 @@ export const Schema = z.object({ }), chartImage: ImageSchema.default({ - __image_url__: "https://example.com/quarterly-chart.png", - __image_prompt__: "Quarterly performance chart showing upward trend" + image_url_: "https://example.com/quarterly-chart.png", + image_prompt_: "Quarterly performance chart showing upward trend" }).meta({ description: "Main performance chart", }), trendIcon: IconSchema.default({ - __icon_url__: "/static/icons/placeholder.png", - __icon_query__: "upward trend arrow icon" + icon_url_: "/static/icons/placeholder.png", + icon_query_: "upward trend arrow icon" }).meta({ description: "Trend indicator icon", }), @@ -57,11 +57,11 @@ export default function ExampleSlideLayout({ data }: { data: SchemaType }) {
- {chartImage?.__image_url__ && ( + {chartImage?.image_url_ && (
{chartImage.__image_prompt__}
@@ -74,9 +74,9 @@ export default function ExampleSlideLayout({ data }: { data: SchemaType }) {
{metric.label} - {trendIcon?.__icon_url__ && ( + {trendIcon?.icon_url_ && ( {metric.trend} diff --git a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx index 5acad87d..62128a40 100644 --- a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx @@ -37,16 +37,16 @@ const type10SlideSchema = z.object({ })).min(2).max(3).default(() => [ { icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'A beautiful road in the mountains' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'A beautiful road in the mountains' }, heading: 'First Key Point', description: 'Detailed explanation of the first important point that supports the main topic' }, { icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'A beautiful road in the mountains' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'A beautiful road in the mountains' }, heading: 'Second Key Point', description: 'Detailed explanation of the second important point with relevant information' @@ -240,9 +240,9 @@ const Type10SlideLayout: React.FC = ({ data: slideData }
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__}
diff --git a/servers/nextjs/presentation-layouts/classic/Type1SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type1SlideLayout.tsx index 75b945ed..5abec5f7 100644 --- a/servers/nextjs/presentation-layouts/classic/Type1SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type1SlideLayout.tsx @@ -14,8 +14,8 @@ const type1SlideSchema = z.object({ description: "Main description text", }), image: ImageSchema.default({ - __image_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', - __image_prompt__: 'A beautiful road in the mountains' + image_url_: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + image_prompt_: 'A beautiful road in the mountains' }).meta({ description: "Main slide image", }) @@ -52,8 +52,8 @@ const Type1SlideLayout: React.FC = ({ data: slideData }) {/* Image */}
{image && {image?.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/classic/Type3SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type3SlideLayout.tsx index f520e7f5..5791eb0f 100644 --- a/servers/nextjs/presentation-layouts/classic/Type3SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type3SlideLayout.tsx @@ -25,24 +25,24 @@ const type3SlideSchema = z.object({ heading: 'First Feature', description: 'Description for the first featured item with detailed information', image: { - __image_url__: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', - __image_prompt__: 'A beautiful road in the mountains' + image_url_: 'https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg', + image_prompt_: 'A beautiful road in the mountains' } }, { heading: 'Second Feature', description: 'Description for the second featured item with relevant details', image: { - __image_url__: 'https://cdn.pixabay.com/photo/2016/02/19/11/19/office-1209640_1280.jpg', - __image_prompt__: 'Modern office workspace' + image_url_: 'https://cdn.pixabay.com/photo/2016/02/19/11/19/office-1209640_1280.jpg', + image_prompt_: 'Modern office workspace' } }, { heading: 'Third Feature', description: 'Description for the third featured item with important points', image: { - __image_url__: 'https://cdn.pixabay.com/photo/2017/08/10/08/47/laptop-2619235_1280.jpg', - __image_prompt__: 'Laptop with code on screen' + image_url_: 'https://cdn.pixabay.com/photo/2017/08/10/08/47/laptop-2619235_1280.jpg', + image_prompt_: 'Laptop with code on screen' } } ]).meta({ @@ -94,8 +94,8 @@ const Type3SlideLayout: React.FC = ({ data: slideData }) {/* Image */}
{item.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx index 004dadd3..d8cf3f7d 100644 --- a/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type6SlideLayout.tsx @@ -23,32 +23,32 @@ const type6SlideSchema = z.object({ heading: 'Professional Service', description: 'High-quality professional services tailored to your specific needs and requirements', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Professional Service' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Professional Service' } }, { heading: 'Expert Consultation', description: 'Expert advice and consultation from experienced professionals in the field', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Expert Consultation' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Expert Consultation' } }, { heading: 'Quality Assurance', description: 'Comprehensive quality assurance processes to ensure excellent results', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Quality Assurance' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Quality Assurance' } }, { heading: 'Customer Support', description: 'Dedicated customer support available to assist you throughout the process', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Customer Support' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Customer Support' } } ]).meta({ @@ -94,7 +94,7 @@ const Type6SlideLayout: React.FC = ({ data: slideData })
- {item.icon.__icon_query__} + {item.icon.icon_query_}
@@ -125,7 +125,7 @@ const Type6SlideLayout: React.FC = ({ data: slideData }) >
- {item.icon.__icon_query__} + {item.icon.icon_query_}
diff --git a/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx index 818e12d1..caa2be34 100644 --- a/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type7SlideLayout.tsx @@ -18,8 +18,8 @@ const type7SlideSchema = z.object({ description: "Item description", }), icon: IconSchema.default({ - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Default icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Default icon' }).meta({ description: "Icon for the item", }) @@ -28,32 +28,32 @@ const type7SlideSchema = z.object({ heading: 'Professional Service', description: 'High-quality professional services tailored to your specific needs and requirements', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Professional service icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Professional service icon' } }, { heading: 'Expert Consultation', description: 'Expert advice and consultation from experienced professionals in the field', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Expert consultation icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Expert consultation icon' } }, { heading: 'Quality Assurance', description: 'Comprehensive quality assurance processes to ensure excellent results', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Quality assurance icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Quality assurance icon' } }, { heading: 'Customer Support', description: 'Dedicated customer support available to assist you throughout the process', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Customer support icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Customer support icon' } } ]).meta({ @@ -100,8 +100,8 @@ const Type7SlideLayout: React.FC = ({ data: slideData })
{item.icon?.__icon_query__
@@ -134,9 +134,9 @@ const Type7SlideLayout: React.FC = ({ data: slideData }) >
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__}
diff --git a/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx index 37002b4b..e3f35005 100644 --- a/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type8SlideLayout.tsx @@ -21,8 +21,8 @@ const type8SlideSchema = z.object({ description: "Item description", }), icon: IconSchema.default({ - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Default icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Default icon' }).meta({ description: "Icon for the item", }) @@ -31,24 +31,24 @@ const type8SlideSchema = z.object({ heading: 'Advanced Features', description: 'Cutting-edge functionality designed to enhance productivity and user experience', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Advanced features icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Advanced features icon' } }, { heading: 'Reliable Performance', description: 'Consistent and dependable performance across all platforms and devices', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Reliable performance icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Reliable performance icon' } }, { heading: 'Secure Environment', description: 'Enterprise-grade security measures to protect your data and privacy', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'Secure environment icon' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'Secure environment icon' } } ]).meta({ @@ -82,9 +82,9 @@ const Type8SlideLayout: React.FC = ({ data: slideData }) >
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__}
@@ -116,9 +116,9 @@ const Type8SlideLayout: React.FC = ({ data: slideData })
- {item.icon?.__icon_url__ && {item.icon?.__icon_query__}
diff --git a/servers/nextjs/presentation-layouts/defaultSchemes.ts b/servers/nextjs/presentation-layouts/defaultSchemes.ts index 45e81f92..b8d0e862 100644 --- a/servers/nextjs/presentation-layouts/defaultSchemes.ts +++ b/servers/nextjs/presentation-layouts/defaultSchemes.ts @@ -1,19 +1,19 @@ import * as z from "zod"; export const ImageSchema = z.object({ - __image_url__: z.url().meta({ + image_url_: z.url().meta({ description: "URL to image", }), - __image_prompt__: z.string().meta({ + image_prompt_: z.string().meta({ description: "Prompt used to generate the image", }).min(10).max(50), }) export const IconSchema = z.object({ - __icon_url__: z.string().meta({ + icon_url_: z.string().meta({ description: "URL to icon", }), - __icon_query__: z.string().meta({ + icon_query_: z.string().meta({ description: "Query used to search the icon", }).min(5).max(20), }) \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/general/BasicInfoSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/BasicInfoSlideLayout.tsx index 0a4132c7..a5aa504b 100644 --- a/servers/nextjs/presentation-layouts/general/BasicInfoSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/BasicInfoSlideLayout.tsx @@ -14,8 +14,8 @@ const basicInfoSlideSchema = z.object({ description: "Main description text content", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Business team in meeting room discussing product features and solutions' + image_url_: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Business team in meeting room discussing product features and solutions' }).meta({ description: "Supporting image for the slide", }) @@ -54,8 +54,8 @@ const BasicInfoSlideLayout: React.FC = ({ data: slide
{slideData?.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/general/BulletIconsOnlySlideLayout.tsx b/servers/nextjs/presentation-layouts/general/BulletIconsOnlySlideLayout.tsx index f4375d7a..d8149949 100644 --- a/servers/nextjs/presentation-layouts/general/BulletIconsOnlySlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/BulletIconsOnlySlideLayout.tsx @@ -11,8 +11,8 @@ const bulletIconsOnlySlideSchema = z.object({ description: "Main title of the slide", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Business professionals collaborating and discussing solutions' + image_url_: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Business professionals collaborating and discussing solutions' }).meta({ description: "Supporting image for the slide", }), @@ -29,32 +29,32 @@ const bulletIconsOnlySlideSchema = z.object({ title: 'Custom Software', subtitle: 'We create tailored software to optimize processes and boost efficiency.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'code software development' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'code software development' } }, { title: 'Digital Consulting', subtitle: 'Our consultants guide organizations in leveraging the latest technologies.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'users consulting team' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'users consulting team' } }, { title: 'Support Services', subtitle: 'We provide ongoing support to help businesses adapt and maintain performance.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'headphones support service' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'headphones support service' } }, { title: 'Scalable Marketing', subtitle: 'Our data-driven strategies help businesses expand their reach and engagement.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'trending up marketing growth' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'trending up marketing growth' } } ]).meta({ @@ -131,8 +131,8 @@ const BulletIconsOnlySlideLayout: React.FC = ({ {/* Icon */}
{bullet.icon.__icon_query__}
@@ -176,8 +176,8 @@ const BulletIconsOnlySlideLayout: React.FC = ({ {/* Main Image */}
{slideData?.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx index c020d4c2..b8927715 100644 --- a/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/BulletWithIconsSlideLayout.tsx @@ -14,8 +14,8 @@ const bulletWithIconsSlideSchema = z.object({ description: "Main description text explaining the problem or topic", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Business people analyzing documents and charts in office' + image_url_: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Business people analyzing documents and charts in office' }).meta({ description: "Supporting image for the slide", }), @@ -32,16 +32,16 @@ const bulletWithIconsSlideSchema = z.object({ title: 'Inefficiency', description: 'Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'warning alert inefficiency' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'warning alert inefficiency' } }, { title: 'High Costs', description: 'Outdated systems increase expenses, while small businesses struggle to expand their market reach.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'trending up costs chart' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'trending up costs chart' } } ]).meta({ @@ -105,8 +105,8 @@ const BulletWithIconsSlideLayout: React.FC = ({
{slideData?.image?.__image_prompt__
@@ -134,8 +134,8 @@ const BulletWithIconsSlideLayout: React.FC = ({ {/* Icon */}
{bullet.icon.__icon_query__}
diff --git a/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx index 47515393..ea714e1f 100644 --- a/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/ChartWithBulletsSlideLayout.tsx @@ -64,24 +64,24 @@ const chartWithBulletsSlideSchema = z.object({ title: 'Total Addressable Market', description: 'Companies can use TAM to plan future expansion and investment.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'target market scope' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'target market scope' } }, { title: 'Serviceable Available Market', description: 'Indicates more measurable market segments for sales efforts.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'pie chart analysis' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'pie chart analysis' } }, { title: 'Serviceable Obtainable Market', description: 'Help companies plan development strategies according to the market.', icon: { - __icon_url__: '/static/icons/placeholder.png', - __icon_query__: 'trending up growth' + icon_url_: '/static/icons/placeholder.png', + icon_query_: 'trending up growth' } } ]).meta({ @@ -270,8 +270,8 @@ const ChartWithBulletsSlideLayout: React.FC =
{bullet.icon.__icon_query__}
diff --git a/servers/nextjs/presentation-layouts/general/IntroSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/IntroSlideLayout.tsx index 347d877d..3fbea7ef 100644 --- a/servers/nextjs/presentation-layouts/general/IntroSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/IntroSlideLayout.tsx @@ -20,8 +20,8 @@ const introSlideSchema = z.object({ description: "Date of the presentation", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Business team in meeting room discussing product features and solutions' + image_url_: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Business team in meeting room discussing product features and solutions' }).meta({ description: "Supporting image for the slide", }) @@ -64,8 +64,8 @@ const IntroSlideLayout: React.FC = ({ data: slideData })
{slideData?.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/general/MetricsWithImageSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/MetricsWithImageSlideLayout.tsx index 65299b90..ad3788c8 100644 --- a/servers/nextjs/presentation-layouts/general/MetricsWithImageSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/MetricsWithImageSlideLayout.tsx @@ -14,8 +14,8 @@ const metricsWithImageSlideSchema = z.object({ description: "Description text below the title", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Person holding tablet with analytics dashboard and charts' + image_url_: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Person holding tablet with analytics dashboard and charts' }).meta({ description: "Supporting image for the slide", }), @@ -86,8 +86,8 @@ const MetricsWithImageSlideLayout: React.FC =
{slideData?.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/general/NumberedBulletsSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/NumberedBulletsSlideLayout.tsx index d8fb2f96..eed1f55a 100644 --- a/servers/nextjs/presentation-layouts/general/NumberedBulletsSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/NumberedBulletsSlideLayout.tsx @@ -11,8 +11,8 @@ const numberedBulletsSlideSchema = z.object({ description: "Main title of the slide", }), image: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', - __image_prompt__: 'Business people analyzing charts and data on wall' + image_url_: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + image_prompt_: 'Business people analyzing charts and data on wall' }).meta({ description: "Supporting image for the slide", }), @@ -87,8 +87,8 @@ const NumberedBulletsSlideLayout: React.FC = ({ {/* Image Section */}
{slideData?.image?.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/general/QuoteSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/QuoteSlideLayout.tsx index bad15379..77c1ce80 100644 --- a/servers/nextjs/presentation-layouts/general/QuoteSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/QuoteSlideLayout.tsx @@ -17,8 +17,8 @@ const quoteSlideSchema = z.object({ description: "Author of the quote", }), backgroundImage: ImageSchema.default({ - __image_url__: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2000&q=80', - __image_prompt__: 'Inspirational mountain landscape with dramatic sky and clouds' + image_url_: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2000&q=80', + image_prompt_: 'Inspirational mountain landscape with dramatic sky and clouds' }).meta({ description: "Background image for the slide", }) @@ -51,7 +51,7 @@ const QuoteSlideLayout: React.FC = ({ data: slideData })
diff --git a/servers/nextjs/presentation-layouts/general/TeamSlideLayout.tsx b/servers/nextjs/presentation-layouts/general/TeamSlideLayout.tsx index 8c7551f6..6dfb0520 100644 --- a/servers/nextjs/presentation-layouts/general/TeamSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/general/TeamSlideLayout.tsx @@ -32,8 +32,8 @@ const teamSlideSchema = z.object({ position: 'CEO', description: 'Strategic leader with 15+ years experience in digital transformation and business growth.', image: { - __image_url__: 'https://images.unsplash.com/photo-1494790108755-2616b612994a?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', - __image_prompt__: 'Professional businesswoman CEO headshot' + image_url_: 'https://images.unsplash.com/photo-1494790108755-2616b612994a?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', + image_prompt_: 'Professional businesswoman CEO headshot' } }, { @@ -41,8 +41,8 @@ const teamSlideSchema = z.object({ position: 'CTO', description: 'Technology expert specializing in scalable solutions and innovative software architecture.', image: { - __image_url__: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', - __image_prompt__: 'Professional businessman CTO headshot' + image_url_: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', + image_prompt_: 'Professional businessman CTO headshot' } }, { @@ -50,8 +50,8 @@ const teamSlideSchema = z.object({ position: 'COO', description: 'Operations leader focused on efficiency, process optimization, and team development.', image: { - __image_url__: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', - __image_prompt__: 'Professional businessman COO headshot' + image_url_: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', + image_prompt_: 'Professional businessman COO headshot' } }, { @@ -59,8 +59,8 @@ const teamSlideSchema = z.object({ position: 'CMO', description: 'Marketing strategist with expertise in brand development and customer engagement.', image: { - __image_url__: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', - __image_prompt__: 'Professional businesswoman CMO headshot' + image_url_: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', + image_prompt_: 'Professional businesswoman CMO headshot' } } ]).meta({ @@ -138,8 +138,8 @@ const TeamSlideLayout: React.FC = ({ data: slideData }) => {/* Member Photo */}
{member.image.__image_prompt__
diff --git a/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx index cea8b48e..16ff9f3e 100644 --- a/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx @@ -71,8 +71,8 @@ const AboutCompanySlideLayout: React.FC = ({
{slideData?.image ? ( {slideData.image.__image_prompt__} ) : ( diff --git a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx index 0471c3c6..6a3bba3c 100644 --- a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx @@ -43,9 +43,9 @@ const problemStatementSlideSchema = z.object({ description: "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { - __icon_url__: + icon_url_: "/static/icons/placeholder.png", - __icon_query__: "warning alert inefficiency", + icon_query_: "warning alert inefficiency", }, }, { @@ -53,9 +53,9 @@ const problemStatementSlideSchema = z.object({ description: "Outdated systems increase expenses, while small businesses struggle to expand their market reach.", icon: { - __icon_url__: + icon_url_: "/static/icons/placeholder.png", - __icon_query__: "trending up costs chart", + icon_query_: "trending up costs chart", }, }, { @@ -63,9 +63,9 @@ const problemStatementSlideSchema = z.object({ description: "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { - __icon_url__: + icon_url_: "/static/icons/placeholder.png", - __icon_query__: "warning alert inefficiency", + icon_query_: "warning alert inefficiency", }, }, { @@ -73,9 +73,9 @@ const problemStatementSlideSchema = z.object({ description: "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", icon: { - __icon_url__: + icon_url_: "/static/icons/placeholder.png", - __icon_query__: "warning alert inefficiency", + icon_query_: "warning alert inefficiency", }, }, ]) @@ -150,10 +150,10 @@ const ProblemStatementSlideLayout: React.FC< className="flex items-start gap-5 bg-white bg-opacity-5 rounded-lg p-5" >
- {category.icon?.__icon_url__ && ( + {category.icon?.icon_url_ && ( {category.icon?.__icon_query__} diff --git a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx index d428e35e..ed7a3a17 100644 --- a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx @@ -49,8 +49,8 @@ const solutionSlideSchema = z.object({ description: "Innovative and widely accepted. Innovative and widely accepted. Innovative and widely accepted.", icon: { - __icon_query__: "market innovation", - __icon_url__: + icon_query_: "market innovation", + icon_url_: "/static/icons/placeholder.png", }, }, @@ -58,8 +58,8 @@ const solutionSlideSchema = z.object({ title: "Industry", description: "Based on sound market decisions.", icon: { - __icon_query__: "industry building", - __icon_url__: + icon_query_: "industry building", + icon_url_: "/static/icons/placeholder.png", }, }, @@ -67,8 +67,8 @@ const solutionSlideSchema = z.object({ title: "SEM", description: "Driven by precise data and analysis.", icon: { - __icon_query__: "SEM data analysis", - __icon_url__: + icon_query_: "SEM data analysis", + icon_url_: "/static/icons/placeholder.png", }, }, @@ -76,8 +76,8 @@ const solutionSlideSchema = z.object({ title: "End User", description: "Focused on real user impact.", icon: { - __icon_query__: "end user impact", - __icon_url__: + icon_query_: "end user impact", + icon_url_: "/static/icons/placeholder.png", }, }, @@ -140,10 +140,10 @@ const SolutionSlideLayout: React.FC = ({ className="flex flex-col items-center text-center bg-[#F5F8FE] rounded-lg shadow px-3 py-4 " >
- {section?.icon?.__icon_url__ && ( + {section?.icon?.icon_url_ && ( {section.icon.__icon_query__} )} diff --git a/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx index c833d106..9bc223eb 100644 --- a/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx @@ -52,9 +52,9 @@ const productOverviewSlideSchema = z.object({ description: "Detail and explain each product. Our examination of community and market issues increases with additional products/services.", image: { - __image_url__: + image_url_: "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=300&h=200&fit=crop", - __image_prompt__: "Person working on electronics with headphones", + image_prompt_: "Person working on electronics with headphones", }, isBlueBackground: true, }, @@ -63,9 +63,9 @@ const productOverviewSlideSchema = z.object({ description: "Our alternate product category is available. Our products must work together to solve social and economic issues.", image: { - __image_url__: + image_url_: "https://images.unsplash.com/photo-1573164713988-8665fc963095?w=300&h=200&fit=crop", - __image_prompt__: + image_prompt_: "Woman working at computer with technical equipment", }, isBlueBackground: true, @@ -163,9 +163,9 @@ const ProductOverviewSlideLayout: React.FC = ({ style={{ height: `${IMAGE_SECTION_HEIGHT + 28}px` }} > { @@ -189,9 +189,9 @@ const ProductOverviewSlideLayout: React.FC = ({ style={{ height: `${IMAGE_SECTION_HEIGHT + 28}px` }} > { diff --git a/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx index 0dd5c5ed..043e9b78 100644 --- a/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx @@ -18,9 +18,9 @@ const marketSizeSlideSchema = z.object({ description: "Today Date displayed in header", }), mapImage: ImageSchema.default({ - __image_url__: + image_url_: "https://upload.wikimedia.org/wikipedia/commons/8/80/World_map_-_low_resolution.svg", // You can quickly find a world map image via a Google search or use a free resource like Wikimedia Commons - __image_prompt__: "World map with location pins or points", + image_prompt_: "World map with location pins or points", }), marketStats: z .array( @@ -111,9 +111,9 @@ const MarketSizeSlideLayout: React.FC = ({ {slideData?.title || "Market Size"}
- {slideData?.mapImage?.__image_url__ && ( + {slideData?.mapImage?.image_url_ && ( Market World Map with Points = ({ > {/* Photo */}
- {member.image.__image_url__ && ( + {member.image.image_url_ && ( {member.image.__image_prompt__ )} diff --git a/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx b/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx index 5b6d9465..abf1a5b6 100644 --- a/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx @@ -39,8 +39,8 @@ export const Schema = z.object({ }), featuredImage: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Professional business team analyzing data and working collaboratively" + image_url_: "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Professional business team analyzing data and working collaboratively" }).meta({ description: "Primary visual that represents the organization's work or environment", }), @@ -127,11 +127,11 @@ const AboutUsSlide = ({ data }: { data: Partial }) => { )} {/* Business Image - Left positioned */} - {featuredImage?.__image_url__ && ( + {featuredImage?.image_url_ && (
{featuredImage.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/BusinessModelSlide.tsx b/servers/nextjs/presentation-layouts/professional/BusinessModelSlide.tsx index 534aa905..a4a70c8e 100644 --- a/servers/nextjs/presentation-layouts/professional/BusinessModelSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/BusinessModelSlide.tsx @@ -33,8 +33,8 @@ export const Schema = z.object({ }), headerVisual: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business strategy meeting with charts, graphs and team collaboration" + image_url_: "https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Business strategy meeting with charts, graphs and team collaboration" }).meta({ description: "Header visual representing the topic area - ADAPT the image prompt to match presentation topic (e.g., 'Climate scientists analyzing global warming data', 'Medical team reviewing patient care protocols', 'Teachers planning educational curriculum')", }), @@ -92,11 +92,11 @@ const BusinessModelSlide = ({ data }: { data: Partial }) => { return (
{/* Header Image Section */} - {headerVisual?.__image_url__ && ( + {headerVisual?.image_url_ && (
{headerVisual.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/MarketSizeSlide.tsx b/servers/nextjs/presentation-layouts/professional/MarketSizeSlide.tsx index df920b88..7c6678cf 100644 --- a/servers/nextjs/presentation-layouts/professional/MarketSizeSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/MarketSizeSlide.tsx @@ -46,8 +46,8 @@ export const Schema = z.object({ }), visualRepresentation: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1597149962419-0d900ac2b46c?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "World map showing global market reach and geographic distribution" + image_url_: "https://images.unsplash.com/photo-1597149962419-0d900ac2b46c?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "World map showing global market reach and geographic distribution" }).meta({ description: "Visual that represents market scope - could be a world map, chart, or geographic visualization", }), @@ -135,11 +135,11 @@ const MarketSizeSlide = ({ data }: { data: Partial }) => { )} {/* Visual Representation */} - {visualRepresentation?.__image_url__ && ( + {visualRepresentation?.image_url_ && (
{visualRepresentation.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx b/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx index e0b55ca0..124cff61 100644 --- a/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx @@ -32,8 +32,8 @@ export const Schema = z.object({ }), serviceHighlight: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1556761175-b413da4baf72?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Professional service delivery or team working on client solutions" + image_url_: "https://images.unsplash.com/photo-1556761175-b413da4baf72?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Professional service delivery or team working on client solutions" }).meta({ description: "Visual that represents service delivery, expertise, or client collaboration", }), @@ -102,11 +102,11 @@ const OurServiceSlide = ({ data }: { data: Partial }) => { {/* Right - Service Highlight */}
{/* Service Highlight Image */} - {serviceHighlight?.__image_url__ && ( + {serviceHighlight?.image_url_ && (
{serviceHighlight.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/ProblemsSlide.tsx b/servers/nextjs/presentation-layouts/professional/ProblemsSlide.tsx index 3a4aee1d..d2444852 100644 --- a/servers/nextjs/presentation-layouts/professional/ProblemsSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/ProblemsSlide.tsx @@ -46,8 +46,8 @@ export const Schema = z.object({ }), supportingVisual: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Professional workspace showing analysis and problem-solving activities" + image_url_: "https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Professional workspace showing analysis and problem-solving activities" }).meta({ description: "Visual that supports the problem discussion - could show analysis, challenges, or work environment", }), @@ -129,11 +129,11 @@ const ProblemsSlide = ({ data }: { data: Partial }) => { )} {/* Supporting Visual */} - {supportingVisual?.__image_url__ && ( + {supportingVisual?.image_url_ && (
{supportingVisual.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/SolutionsSlide.tsx b/servers/nextjs/presentation-layouts/professional/SolutionsSlide.tsx index 5eb91707..a2b076bf 100644 --- a/servers/nextjs/presentation-layouts/professional/SolutionsSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/SolutionsSlide.tsx @@ -46,15 +46,15 @@ export const Schema = z.object({ }), primaryVisual: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Modern workspace with team collaboration and strategic planning" + image_url_: "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Modern workspace with team collaboration and strategic planning" }).meta({ description: "Primary visual representing teamwork, strategy, or solution implementation", }), brandingVisual: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/150x80/22C55E/FFFFFF?text=LOGO", - __image_prompt__: "Organization logo or brand mark" + image_url_: "https://via.placeholder.com/150x80/22C55E/FFFFFF?text=LOGO", + image_prompt_: "Organization logo or brand mark" }).meta({ description: "Logo or branding element to maintain visual identity", }), @@ -93,11 +93,11 @@ const SolutionsSlide = ({ data }: { data: Partial }) => { {/* Left Side - Images and Branding */}
{/* Top Image Area */} - {primaryVisual?.__image_url__ && ( + {primaryVisual?.image_url_ && (
{primaryVisual.__image_prompt__}
@@ -105,10 +105,10 @@ const SolutionsSlide = ({ data }: { data: Partial }) => { {/* Bottom Branding Area */}
- {brandingVisual?.__image_url__ && ( + {brandingVisual?.image_url_ && ( {brandingVisual.__image_prompt__} )} diff --git a/servers/nextjs/presentation-layouts/professional/StatisticCircularSlide.tsx b/servers/nextjs/presentation-layouts/professional/StatisticCircularSlide.tsx index 3b939f8f..2067cb32 100644 --- a/servers/nextjs/presentation-layouts/professional/StatisticCircularSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/StatisticCircularSlide.tsx @@ -29,8 +29,8 @@ export const Schema = z.object({ }), brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: "Professional organization logo - clean and modern design" + image_url_: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + image_prompt_: "Professional organization logo - clean and modern design" }).meta({ description: "Logo or brand mark representing the organization", }), @@ -67,8 +67,8 @@ export const Schema = z.object({ }), companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", - __image_prompt__: "Clean modern company logo icon in white" + image_url_: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", + image_prompt_: "Clean modern company logo icon in white" }).meta({ description: "Company logo icon", }), @@ -128,11 +128,11 @@ const StatisticCircularSlide = ({ data }: { data: Partial }) => { {/* Right - Company Branding */}
- {companyLogo?.__image_url__ && ( + {companyLogo?.image_url_ && (
{companyLogo.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/StatisticDualChartSlide.tsx b/servers/nextjs/presentation-layouts/professional/StatisticDualChartSlide.tsx index aa5d2f42..b33d2a9d 100644 --- a/servers/nextjs/presentation-layouts/professional/StatisticDualChartSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/StatisticDualChartSlide.tsx @@ -24,8 +24,8 @@ export const Schema = z.object({ }), brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: "Professional organization logo - clean and modern design" + image_url_: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + image_prompt_: "Professional organization logo - clean and modern design" }).meta({ description: "Logo or brand mark representing the organization", }), @@ -130,11 +130,11 @@ const StatisticDualChartSlide = ({ data }: { data: Partial }) => { {/* Company Branding */}
- {brandLogo?.__image_url__ && ( + {brandLogo?.image_url_ && (
{brandLogo.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/StatisticSlide.tsx b/servers/nextjs/presentation-layouts/professional/StatisticSlide.tsx index 15a85c27..47a2945e 100644 --- a/servers/nextjs/presentation-layouts/professional/StatisticSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/StatisticSlide.tsx @@ -40,8 +40,8 @@ export const Schema = z.object({ }), supportingVisual: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business analytics dashboard with charts and data visualization" + image_url_: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Business analytics dashboard with charts and data visualization" }).meta({ description: "ADAPT the image prompt to match the presentation topic: For global warming: 'Climate monitoring station with temperature sensors and weather equipment', 'Scientists analyzing ice core data in Arctic research facility'. For healthcare: 'Medical monitoring equipment displaying patient vital signs', 'Healthcare analytics dashboard showing treatment outcomes'. For education: 'Educational assessment data on computer screens', 'Students using digital learning platforms'.", }), @@ -148,12 +148,12 @@ const StatisticSlide = ({ data }: { data: Partial }) => {
{/* Business Image */} - {supportingVisual?.__image_url__ && ( + {supportingVisual?.image_url_ && (
{supportingVisual.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/TableOfContentsSlide.tsx b/servers/nextjs/presentation-layouts/professional/TableOfContentsSlide.tsx index 261fe221..81e2e49a 100644 --- a/servers/nextjs/presentation-layouts/professional/TableOfContentsSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/TableOfContentsSlide.tsx @@ -61,8 +61,8 @@ export const Schema = z.object({ }), brandingVisual: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/200x100/22C55E/FFFFFF?text=BRAND", - __image_prompt__: "Organization logo or brand visual element" + image_url_: "https://via.placeholder.com/200x100/22C55E/FFFFFF?text=BRAND", + image_prompt_: "Organization logo or brand visual element" }).meta({ description: "Logo or branding element displayed prominently for visual identity", }), @@ -146,11 +146,11 @@ const TableOfContentsSlide = ({ data }: { data: Partial }) => { {/* Right Side - Branding and Visual Elements */}
{/* Branding Visual */} - {brandingVisual?.__image_url__ && ( + {brandingVisual?.image_url_ && (
{brandingVisual.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/TestimonialSlide.tsx b/servers/nextjs/presentation-layouts/professional/TestimonialSlide.tsx index 25fe2f88..8dac0093 100644 --- a/servers/nextjs/presentation-layouts/professional/TestimonialSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/TestimonialSlide.tsx @@ -22,8 +22,8 @@ export const Schema = z.object({ }), brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: "Professional organization logo - clean and modern design" + image_url_: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + image_prompt_: "Professional organization logo - clean and modern design" }).meta({ description: "Logo or brand mark representing the organization", }), @@ -43,8 +43,8 @@ export const Schema = z.object({ testimonialText: "Working with this team has been transformative for our business. Their expertise, dedication, and innovative approach exceeded our expectations and delivered remarkable results.", rating: 5, clientPhoto: { - __image_url__: "https://images.unsplash.com/photo-1494790108755-2616b612b830?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional businesswoman headshot" + image_url_: "https://images.unsplash.com/photo-1494790108755-2616b612b830?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + image_prompt_: "Professional businesswoman headshot" } }, { @@ -54,8 +54,8 @@ export const Schema = z.object({ testimonialText: "The level of professionalism and quality of service provided was outstanding. They understood our needs perfectly and delivered solutions that truly made a difference.", rating: 5, clientPhoto: { - __image_url__: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional businessman headshot" + image_url_: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + image_prompt_: "Professional businessman headshot" } }, { @@ -65,8 +65,8 @@ export const Schema = z.object({ testimonialText: "Exceptional service and results that spoke for themselves. The team's attention to detail and commitment to excellence made our collaboration highly successful.", rating: 5, clientPhoto: { - __image_url__: "https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional woman headshot" + image_url_: "https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + image_prompt_: "Professional woman headshot" } } ]).meta({ @@ -121,11 +121,11 @@ const TestimonialSlide = ({ data }: { data: Partial }) => { {/* Company Branding */}
- {brandLogo?.__image_url__ && ( + {brandLogo?.image_url_ && (
{brandLogo.__image_prompt__}
@@ -164,11 +164,11 @@ const TestimonialSlide = ({ data }: { data: Partial }) => { {/* Client Info */}
{/* Client Photo */} - {showClientPhotos && item.clientPhoto?.__image_url__ && ( + {showClientPhotos && item.clientPhoto?.image_url_ && (
{item.clientPhoto.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/ThankYouSlide.tsx b/servers/nextjs/presentation-layouts/professional/ThankYouSlide.tsx index 237e3e0d..38c37a51 100644 --- a/servers/nextjs/presentation-layouts/professional/ThankYouSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/ThankYouSlide.tsx @@ -30,8 +30,8 @@ export const Schema = z.object({ }), brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: "Professional organization logo - clean and modern design" + image_url_: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + image_prompt_: "Professional organization logo - clean and modern design" }).meta({ description: "Logo or brand mark representing the presenting organization", }), @@ -89,11 +89,11 @@ const ThankYouSlide = ({ data }: { data: Partial }) => {
{/* Company Logo and Name */}
- {brandLogo?.__image_url__ && ( + {brandLogo?.image_url_ && (
{brandLogo.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/TitleSlide.tsx b/servers/nextjs/presentation-layouts/professional/TitleSlide.tsx index 5de16285..dd8d6d4f 100644 --- a/servers/nextjs/presentation-layouts/professional/TitleSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/TitleSlide.tsx @@ -30,8 +30,8 @@ export const Schema = z.object({ }), brandLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", - __image_prompt__: "Professional organization logo - clean and modern design" + image_url_: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + image_prompt_: "Professional organization logo - clean and modern design" }).meta({ description: "Logo or brand mark representing the presenting organization", }), @@ -84,11 +84,11 @@ const ThynkTitleSlide = ({ data }: { data: Partial }) => {
{/* Company Logo and Name */}
- {brandLogo?.__image_url__ && ( + {brandLogo?.image_url_ && (
{brandLogo.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/professional/WhatWeBelieveSlide.tsx b/servers/nextjs/presentation-layouts/professional/WhatWeBelieveSlide.tsx index 95c9bdb7..0b167434 100644 --- a/servers/nextjs/presentation-layouts/professional/WhatWeBelieveSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/WhatWeBelieveSlide.tsx @@ -40,8 +40,8 @@ export const Schema = z.object({ }), supportingVisual: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Diverse team collaborating and planning together in modern workspace" + image_url_: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + image_prompt_: "Diverse team collaborating and planning together in modern workspace" }).meta({ description: "Visual that represents collaboration, vision, or organizational culture", }), @@ -73,11 +73,11 @@ const WhatWeBelieveSlide = ({ data }: { data: Partial }) => {
{/* Left Side - Image */}
- {supportingVisual?.__image_url__ && ( + {supportingVisual?.image_url_ && (
{supportingVisual.__image_prompt__}
diff --git a/servers/nextjs/store/slices/presentationGeneration.ts b/servers/nextjs/store/slices/presentationGeneration.ts index 5044629a..947df5e3 100644 --- a/servers/nextjs/store/slices/presentationGeneration.ts +++ b/servers/nextjs/store/slices/presentationGeneration.ts @@ -260,8 +260,8 @@ const presentationGenerationSlice = createSlice({ // Preserve existing properties if the target already exists const updatedValue = { ...(target && typeof target === 'object' ? target : {}), - __image_url__: url, - __image_prompt__: promptText || (target?.__image_prompt__) || '' + image_url_: url, + image_prompt_: promptText || (target?.image_prompt_) || '' }; if (isNaN(Number(finalKey))) { @@ -359,8 +359,8 @@ const presentationGenerationSlice = createSlice({ // Preserve existing properties if the target already exists const updatedValue = { ...(target && typeof target === 'object' ? target : {}), - __icon_url__: url, - __icon_query__: queryText || (target?.__icon_query__) || '' + icon_url_: url, + icon_query_: queryText || (target?.icon_query_) || '' }; if (isNaN(Number(finalKey))) {