adserver-dashboard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ci/staging.yml +191 -0
- package/.dockerignore +117 -0
- package/.env +40 -0
- package/.env.staging +38 -0
- package/.gitlab-ci.yml +16 -0
- package/DEMO_STATUS.md +579 -0
- package/Dockerfile +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/index.html +17 -0
- package/Influence-MW-AdServer-12-02-2026/client/public/favicon.png +0 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/App.tsx +91 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/advanced-map-drawer.tsx +1131 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ai-recommendation-panel.tsx +379 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/app-sidebar.tsx +183 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/auto-optimize-button.tsx +184 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/availability-drawer.tsx +385 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/brand-insights-panel.tsx +87 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-agency-drawer.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-brand-drawer.tsx +275 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/creative-assignment.tsx +526 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table-toolbar.tsx +148 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table.tsx +158 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/filter-drawer.tsx +356 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/form-insights-panel.tsx +82 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/geography-selector.tsx +699 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/header-user-menu.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/history-drawer.tsx +313 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-availability-section.tsx +176 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-format-drawer.tsx +173 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-selector.tsx +401 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/manual-inventory-drawer.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/mapbox-map.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/market-insights-panel.tsx +202 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/media-owner-drawer.tsx +217 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/metric-card.tsx +58 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/page-header.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/player-status-indicator.tsx +137 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/poi-targeting-drawer.tsx +298 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommendation-score-badge.tsx +102 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommended-inventories-panel.tsx +248 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/searchable-combobox.tsx +134 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/signal-visualizations.tsx +407 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/status-badge.tsx +35 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-provider.tsx +73 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-toggle.tsx +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/traffic-slider.tsx +75 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/accordion.tsx +56 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert-dialog.tsx +139 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert.tsx +59 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/aspect-ratio.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/avatar.tsx +51 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/badge.tsx +38 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/breadcrumb.tsx +115 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/button.tsx +62 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/calendar.tsx +68 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/card.tsx +85 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/carousel.tsx +260 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/chart.tsx +365 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/checkbox.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/collapsible.tsx +11 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/command.tsx +151 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/context-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dialog.tsx +122 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/drawer.tsx +118 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dropdown-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/form.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/hover-card.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input-otp.tsx +69 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input.tsx +23 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/label.tsx +24 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/menubar.tsx +256 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/navigation-menu.tsx +128 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/pagination.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/popover.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/progress.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/radio-group.tsx +42 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/resizable.tsx +45 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/scroll-area.tsx +46 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/select.tsx +160 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/separator.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sheet.tsx +140 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sidebar.tsx +727 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/skeleton.tsx +15 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/slider.tsx +26 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/switch.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/table.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tabs.tsx +53 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/textarea.tsx +22 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toast.tsx +127 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toaster.tsx +33 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle-group.tsx +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle.tsx +43 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tooltip.tsx +30 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/vendor-stores-modal.tsx +336 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-drawer.tsx +359 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-selector.tsx +436 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-mobile.tsx +19 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-toast.ts +191 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/index.css +244 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/queryClient.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/utils.ts +39 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/venue-taxonomy.ts +532 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/main.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/assign-creative.tsx +781 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/content-hub.tsx +995 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/custom-pois.tsx +431 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/dashboard.tsx +620 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-detail.tsx +1062 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-form.tsx +1570 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deals.tsx +716 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/edit-creative-assignment.tsx +1051 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/geotargeting.tsx +675 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/integrations.tsx +425 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-creatives.tsx +622 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-form.tsx +3132 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-items.tsx +530 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/not-found.tsx +21 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play-upload.tsx +479 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play.tsx +880 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/reports.tsx +235 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/settings.tsx +652 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signal-form.tsx +1117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signals.tsx +366 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/tags.tsx +332 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/venues.tsx +381 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/mapbox-gl-draw.d.ts +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/react-simple-maps.d.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/components.json +20 -0
- package/Influence-MW-AdServer-12-02-2026/docs/PRD.md +3373 -0
- package/Influence-MW-AdServer-12-02-2026/docs/influence-feature-mapping.csv +498 -0
- package/Influence-MW-AdServer-12-02-2026/drizzle.config.ts +14 -0
- package/Influence-MW-AdServer-12-02-2026/package-lock.json +9672 -0
- package/Influence-MW-AdServer-12-02-2026/package.json +118 -0
- package/Influence-MW-AdServer-12-02-2026/postcss.config.js +6 -0
- package/Influence-MW-AdServer-12-02-2026/replit.md +91 -0
- package/Influence-MW-AdServer-12-02-2026/script/build.ts +67 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-miro-diagrams.cjs +318 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-remaining-diagrams.cjs +270 -0
- package/Influence-MW-AdServer-12-02-2026/server/index.ts +103 -0
- package/Influence-MW-AdServer-12-02-2026/server/recommendation-service.ts +319 -0
- package/Influence-MW-AdServer-12-02-2026/server/routes.ts +1890 -0
- package/Influence-MW-AdServer-12-02-2026/server/static.ts +19 -0
- package/Influence-MW-AdServer-12-02-2026/server/storage.ts +2058 -0
- package/Influence-MW-AdServer-12-02-2026/server/vite.ts +58 -0
- package/Influence-MW-AdServer-12-02-2026/shared/schema.ts +1595 -0
- package/Influence-MW-AdServer-12-02-2026/tailwind.config.ts +107 -0
- package/Influence-MW-AdServer-12-02-2026/tsconfig.json +23 -0
- package/Influence-MW-AdServer-12-02-2026/vite.config.ts +40 -0
- package/LINE_ITEM_BUDGET_FIELD_MAPPING.md +178 -0
- package/PCM/.env.example +92 -0
- package/PCM/README.md +558 -0
- package/PCM/docs/TEST_CASES.md +422 -0
- package/PCM/index.js +106 -0
- package/PCM/package-lock.json +3282 -0
- package/PCM/package.json +32 -0
- package/PCM/replit.md +64 -0
- package/PCM/schema.sql +495 -0
- package/PCM/scripts/export-schema.js +183 -0
- package/PCM/scripts/seed-comprehensive.js +631 -0
- package/PCM/scripts/seed-production.js +477 -0
- package/PCM/src/config/db.js +56 -0
- package/PCM/src/config/swagger.js +5975 -0
- package/PCM/src/dto/EmailRequestDTO.js +166 -0
- package/PCM/src/middleware/errorHandler.js +52 -0
- package/PCM/src/middleware/logger.js +26 -0
- package/PCM/src/migrations/001_add_campaign_mode_fields.sql +36 -0
- package/PCM/src/migrations/002_create_deal_id_counters.sql +22 -0
- package/PCM/src/migrations/003_update_publishers_column.sql +15 -0
- package/PCM/src/migrations/004_add_direct_dealtype_and_advertiser.sql +5 -0
- package/PCM/src/migrations/005_add_programmatic_fields_and_update_enums.sql +31 -0
- package/PCM/src/migrations/006_add_line_item_programmatic_fields.sql +12 -0
- package/PCM/src/migrations/007_add_line_item_direct_fields.sql +15 -0
- package/PCM/src/migrations/008_add_inventory_fields.sql +45 -0
- package/PCM/src/migrations/009_move_inventory_fields_to_metadata.sql +32 -0
- package/PCM/src/migrations/010_add_draft_status_and_line_items_count.sql +23 -0
- package/PCM/src/migrations/011_add_planning_field.sql +21 -0
- package/PCM/src/migrations/012_fix_inventory_composite_pk.sql +17 -0
- package/PCM/src/migrations/013_make_external_id_optional.sql +3 -0
- package/PCM/src/migrations/014_create_change_history.sql +38 -0
- package/PCM/src/migrations/016_create_publisher_insertion_orders.sql +33 -0
- package/PCM/src/migrations/017_fix_line_item_id_fk_reference.sql +86 -0
- package/PCM/src/migrations/018_create_approval_tables.sql +44 -0
- package/PCM/src/migrations/019_add_encrypted_token_column.sql +2 -0
- package/PCM/src/migrations/020_add_rejection_reason_to_deals.sql +10 -0
- package/PCM/src/migrations/021_add_publisher_external_id_to_inventories.sql +12 -0
- package/PCM/src/migrations/022_add_line_item_extended_fields.sql +24 -0
- package/PCM/src/migrations/023_add_base_price_fields.sql +8 -0
- package/PCM/src/migrations/run-migrations.js +46 -0
- package/PCM/src/models/ApprovalOTP.js +51 -0
- package/PCM/src/models/ApprovalToken.js +79 -0
- package/PCM/src/models/ChangeHistory.js +107 -0
- package/PCM/src/models/Deal.js +186 -0
- package/PCM/src/models/DealIdCounter.js +28 -0
- package/PCM/src/models/LineItem.js +227 -0
- package/PCM/src/models/LineItemCreative.js +89 -0
- package/PCM/src/models/LineItemInventory.js +115 -0
- package/PCM/src/models/PublisherInsertionOrder.js +93 -0
- package/PCM/src/models/TransactionHistory.js +34 -0
- package/PCM/src/models/associations.js +81 -0
- package/PCM/src/routes/approval.js +321 -0
- package/PCM/src/routes/creatives.js +437 -0
- package/PCM/src/routes/deals.js +1638 -0
- package/PCM/src/routes/digitalSignage.js +242 -0
- package/PCM/src/routes/insertionOrders.js +380 -0
- package/PCM/src/routes/lineItems.js +926 -0
- package/PCM/src/routes/system.js +384 -0
- package/PCM/src/services/ApprovalService.js +885 -0
- package/PCM/src/services/CampaignImportConverter.js +631 -0
- package/PCM/src/services/CampaignModeService.js +273 -0
- package/PCM/src/services/CampaignStatusService.js +395 -0
- package/PCM/src/services/ChangeHistoryService.js +316 -0
- package/PCM/src/services/DealIdService.js +94 -0
- package/PCM/src/services/DealResponseFormatter.js +90 -0
- package/PCM/src/services/EmailNotificationService.js +315 -0
- package/PCM/src/services/LineItemResponseFormatter.js +122 -0
- package/PCM/src/services/LineItemStatusService.js +380 -0
- package/PCM/src/tests/comprehensiveTestRunner.js +360 -0
- package/PCM/src/tests/comprehensiveTests.js +1277 -0
- package/PCM/src/tests/dealTypeUnitTests.js +1058 -0
- package/PCM/src/tests/testRunner.js +248 -0
- package/PCM/src/utils/caseConverter.js +92 -0
- package/PCM/src/utils/dealCalculations.js +206 -0
- package/PCM/src/utils/lineItemPayloadNormalizer.js +41 -0
- package/PCM/src/utils/payloadNormalizer.js +34 -0
- package/PCM/src/utils/sourceNormalizer.js +56 -0
- package/PCM/src/validators/creativeValidator.js +27 -0
- package/PCM/src/validators/dealValidator.js +203 -0
- package/PCM/src/validators/lineItemValidator.js +489 -0
- package/PCM/tests/approval-flows.test.js +238 -0
- package/PCM/tests/approval-workflow.test.js +291 -0
- package/PCM/tests/campaign-import-converter.test.js +543 -0
- package/PCM/tests/campaign-import-e2e.test.js +520 -0
- package/PCM/tests/campaign-status.test.js +539 -0
- package/PCM/tests/direct-publisher-split-reimport.test.js +460 -0
- package/PCM/tests/e2e/digital-signage.test.js +145 -0
- package/PCM/tests/e2e/search-filter-pagination.test.js +399 -0
- package/PCM/tests/e2e-comprehensive.test.js +3446 -0
- package/PCM/tests/edge-cases.test.js +340 -0
- package/PCM/tests/line-item-status.test.js +340 -0
- package/PCM/tests/seller-account-external-ids.test.js +877 -0
- package/PCM/tests/source-validation.test.js +324 -0
- package/PRD.md +3373 -0
- package/README.md +186 -0
- package/client/index.html +35 -0
- package/client/public/DEMO_STATUS.md +579 -0
- package/client/public/img/MW-logo-trans_1754045676555.png +0 -0
- package/client/public/locales/ar/approval.json +144 -0
- package/client/public/locales/ar/buyer.json +61 -0
- package/client/public/locales/ar/campaigns.json +1 -0
- package/client/public/locales/ar/common.json +218 -0
- package/client/public/locales/ar/contentHub.json +266 -0
- package/client/public/locales/ar/creatives.json +79 -0
- package/client/public/locales/ar/dashboard.json +57 -0
- package/client/public/locales/ar/deals.json +886 -0
- package/client/public/locales/ar/dsp.json +131 -0
- package/client/public/locales/ar/inventory.json +201 -0
- package/client/public/locales/ar/lineItems.json +553 -0
- package/client/public/locales/ar/navigation.json +48 -0
- package/client/public/locales/ar/wizard.json +1 -0
- package/client/public/locales/en/approval.json +144 -0
- package/client/public/locales/en/buyer.json +65 -0
- package/client/public/locales/en/campaigns.json +1 -0
- package/client/public/locales/en/common.json +218 -0
- package/client/public/locales/en/contentHub.json +266 -0
- package/client/public/locales/en/creatives.json +79 -0
- package/client/public/locales/en/dashboard.json +57 -0
- package/client/public/locales/en/deals.json +886 -0
- package/client/public/locales/en/dsp.json +131 -0
- package/client/public/locales/en/inventory.json +201 -0
- package/client/public/locales/en/lineItems.json +659 -0
- package/client/public/locales/en/navigation.json +48 -0
- package/client/public/locales/en/wizard.json +1 -0
- package/client/public/locales/ja/approval.json +144 -0
- package/client/public/locales/ja/buyer.json +61 -0
- package/client/public/locales/ja/campaigns.json +1 -0
- package/client/public/locales/ja/common.json +218 -0
- package/client/public/locales/ja/contentHub.json +266 -0
- package/client/public/locales/ja/creatives.json +79 -0
- package/client/public/locales/ja/dashboard.json +57 -0
- package/client/public/locales/ja/deals.json +886 -0
- package/client/public/locales/ja/dsp.json +131 -0
- package/client/public/locales/ja/inventory.json +201 -0
- package/client/public/locales/ja/lineItems.json +553 -0
- package/client/public/locales/ja/navigation.json +48 -0
- package/client/public/locales/ja/wizard.json +1 -0
- package/client/public/locales/zh/approval.json +144 -0
- package/client/public/locales/zh/buyer.json +61 -0
- package/client/public/locales/zh/campaigns.json +1 -0
- package/client/public/locales/zh/common.json +218 -0
- package/client/public/locales/zh/contentHub.json +266 -0
- package/client/public/locales/zh/creatives.json +79 -0
- package/client/public/locales/zh/dashboard.json +57 -0
- package/client/public/locales/zh/deals.json +886 -0
- package/client/public/locales/zh/dsp.json +131 -0
- package/client/public/locales/zh/inventory.json +201 -0
- package/client/public/locales/zh/lineItems.json +553 -0
- package/client/public/locales/zh/navigation.json +48 -0
- package/client/public/locales/zh/wizard.json +1 -0
- package/client/public/manifest.json +36 -0
- package/client/src/App.tsx +464 -0
- package/client/src/components/app-sidebar.tsx +312 -0
- package/client/src/components/approval/approval-decision-form.test.tsx +294 -0
- package/client/src/components/approval/approval-decision-form.tsx +326 -0
- package/client/src/components/approval/approval-sheet.tsx +631 -0
- package/client/src/components/approval/line-item-details-sheet.tsx +371 -0
- package/client/src/components/approval/otp-verification.test.tsx +337 -0
- package/client/src/components/approval/otp-verification.tsx +180 -0
- package/client/src/components/content-hub/bulk-transcode-dialog.tsx +379 -0
- package/client/src/components/content-hub/content-hub-manager-v2.tsx +574 -0
- package/client/src/components/content-hub/content-hub-manager.tsx +330 -0
- package/client/src/components/content-hub/creative-card.tsx +456 -0
- package/client/src/components/content-hub/creative-detail-sheet.tsx +685 -0
- package/client/src/components/content-hub/creative-filters.tsx +457 -0
- package/client/src/components/content-hub/creative-grid.tsx +329 -0
- package/client/src/components/content-hub/creative-selector.tsx +415 -0
- package/client/src/components/content-hub/creative-upload.tsx +547 -0
- package/client/src/components/content-hub/folder-dialogs.tsx +445 -0
- package/client/src/components/content-hub/folder-list.tsx +280 -0
- package/client/src/components/content-hub/review-dialogs.tsx +268 -0
- package/client/src/components/content-hub/transcode-dialog.tsx +226 -0
- package/client/src/components/creative-library/creative-details-view.tsx +446 -0
- package/client/src/components/creative-library/creative-filters-panel.tsx +203 -0
- package/client/src/components/creative-library/creative-list.tsx +360 -0
- package/client/src/components/creative-library/creative-status-badge.tsx +71 -0
- package/client/src/components/creative-library/folder-card.tsx +78 -0
- package/client/src/components/creative-library/index.ts +27 -0
- package/client/src/components/creative-library/new-creative-card.tsx +211 -0
- package/client/src/components/creative-library/upload-creative-dialog.tsx +261 -0
- package/client/src/components/dashboard-overview.tsx +109 -0
- package/client/src/components/deals/approval-history-panel.test.tsx +240 -0
- package/client/src/components/deals/approval-history-panel.tsx +156 -0
- package/client/src/components/deals/deal-status-badge.tsx +92 -0
- package/client/src/components/deals/import-from-planner-dialog.tsx +399 -0
- package/client/src/components/deals/market-insights-panel.tsx +237 -0
- package/client/src/components/deals/reopen-deal-sheet.tsx +191 -0
- package/client/src/components/deals/request-approval-sheet.test.tsx +323 -0
- package/client/src/components/deals/request-approval-sheet.tsx +136 -0
- package/client/src/components/deals/resend-approval-sheet.tsx +201 -0
- package/client/src/components/direct-campaigns/campaign-card.tsx +283 -0
- package/client/src/components/direct-campaigns/deal-filter-panel.tsx +325 -0
- package/client/src/components/inventory/advanced-filters-panel.tsx +273 -0
- package/client/src/components/inventory/csv-upload-modal.tsx +639 -0
- package/client/src/components/inventory/inventory-availability-view.tsx +486 -0
- package/client/src/components/inventory/inventory-details-sheet.tsx +376 -0
- package/client/src/components/inventory/inventory-map-view.tsx +596 -0
- package/client/src/components/inventory/inventory-settings-menu.tsx +52 -0
- package/client/src/components/language-switcher.tsx +53 -0
- package/client/src/components/line-items/campaign-forecast-panel.tsx +138 -0
- package/client/src/components/line-items/form-insights.tsx +89 -0
- package/client/src/components/line-items/geofencing/LocationCsvUploadDrawer.tsx +100 -0
- package/client/src/components/line-items/geofencing/POIDropdown.tsx +379 -0
- package/client/src/components/line-items/geofencing/SelectedLocationsSidebar.tsx +436 -0
- package/client/src/components/line-items/geofencing/ViewFileLocationDrawer.tsx +199 -0
- package/client/src/components/line-items/geofencing/components/ExistingFilesTab.tsx +268 -0
- package/client/src/components/line-items/geofencing/components/TemplateDownloadSection.tsx +59 -0
- package/client/src/components/line-items/geofencing/components/UploadTab.tsx +215 -0
- package/client/src/components/line-items/geofencing-map.tsx +1270 -0
- package/client/src/components/line-items/inventory-availability-section.tsx +178 -0
- package/client/src/components/line-items/line-item-schedule-manager.tsx +313 -0
- package/client/src/components/line-items/manual-inventory-drawer.tsx +346 -0
- package/client/src/components/line-items/planner-inventory-card.tsx +495 -0
- package/client/src/components/line-items/planner-schedule-grid.tsx +495 -0
- package/client/src/components/line-items/schedule-rule-editor.tsx +649 -0
- package/client/src/components/line-items/schedule-rule-types.ts +122 -0
- package/client/src/components/line-items/steps/creatives-step.tsx +681 -0
- package/client/src/components/line-items/steps/inventory-schedule-step.tsx +1596 -0
- package/client/src/components/line-items/steps/inventory-step.tsx +1533 -0
- package/client/src/components/line-items/steps/line-item-details-step.tsx +916 -0
- package/client/src/components/line-items/steps/schedule-step.tsx +273 -0
- package/client/src/components/line-items/steps/summary-step.tsx +680 -0
- package/client/src/components/line-items/steps/targeting-step.tsx +1708 -0
- package/client/src/components/product-switcher.tsx +105 -0
- package/client/src/components/protected-route.tsx +49 -0
- package/client/src/components/skip-link.tsx +22 -0
- package/client/src/components/stat-card.tsx +53 -0
- package/client/src/components/status-badge.tsx +96 -0
- package/client/src/components/ui/hierarchical-venue-selector.tsx +389 -0
- package/client/src/components/ui/toaster.tsx +111 -0
- package/client/src/contexts/auth-context.tsx +181 -0
- package/client/src/contexts/sidebar-state.tsx +50 -0
- package/client/src/contexts/theme-context.tsx +66 -0
- package/client/src/data/campaign-data.json +107 -0
- package/client/src/data/countries.json +22 -0
- package/client/src/hooks/use-approval.ts +366 -0
- package/client/src/hooks/use-keyboard-shortcuts.ts +74 -0
- package/client/src/hooks/use-media-query.ts +46 -0
- package/client/src/hooks/use-mobile.tsx +19 -0
- package/client/src/hooks/use-page-title.ts +21 -0
- package/client/src/hooks/use-toast.ts +195 -0
- package/client/src/index.css +694 -0
- package/client/src/lib/__tests__/accessibility.test.ts +104 -0
- package/client/src/lib/__tests__/date-utils.test.ts +199 -0
- package/client/src/lib/__tests__/dsp-buyer-api.test.ts +127 -0
- package/client/src/lib/__tests__/dsp-buyer-integration.test.ts +247 -0
- package/client/src/lib/__tests__/storage-utils.test.ts +167 -0
- package/client/src/lib/__tests__/utils.test.ts +57 -0
- package/client/src/lib/accessibility.ts +141 -0
- package/client/src/lib/api-config.ts +9 -0
- package/client/src/lib/auth-service.ts +209 -0
- package/client/src/lib/campaign-creative-api.ts +82 -0
- package/client/src/lib/company-api.ts +61 -0
- package/client/src/lib/content-hub-api.ts +407 -0
- package/client/src/lib/creative-mapper.ts +61 -0
- package/client/src/lib/date-utils.ts +119 -0
- package/client/src/lib/deal-helpers.ts +220 -0
- package/client/src/lib/dsp-buyer-api.ts +196 -0
- package/client/src/lib/geo-import-api.ts +151 -0
- package/client/src/lib/google-poi-api.ts +305 -0
- package/client/src/lib/i18n/__tests__/formatting.test.ts +202 -0
- package/client/src/lib/i18n/formatting.ts +130 -0
- package/client/src/lib/i18n/index.ts +8 -0
- package/client/src/lib/i18n-compat.ts +76 -0
- package/client/src/lib/influence-deals-api.ts +896 -0
- package/client/src/lib/inventory-api.ts +399 -0
- package/client/src/lib/oauth-service.ts +678 -0
- package/client/src/lib/poi-types.ts +75 -0
- package/client/src/lib/queryClient.ts +144 -0
- package/client/src/lib/recommendation-api.ts +380 -0
- package/client/src/lib/storage-utils.ts +104 -0
- package/client/src/lib/tolgee.ts +85 -0
- package/client/src/lib/utils.ts +0 -0
- package/client/src/main.tsx +67 -0
- package/client/src/mapbox-draw-modes.d.ts +32 -0
- package/client/src/pages/all-folders.tsx +203 -0
- package/client/src/pages/auth-callback.tsx +115 -0
- package/client/src/pages/buyer-form.tsx +339 -0
- package/client/src/pages/buyer-list.tsx +622 -0
- package/client/src/pages/content-hub.tsx +1358 -0
- package/client/src/pages/create-deal.tsx +2093 -0
- package/client/src/pages/creative-assignment-page.tsx +548 -0
- package/client/src/pages/creatives.tsx +5 -0
- package/client/src/pages/custom-pois.tsx +425 -0
- package/client/src/pages/dashboard.tsx +615 -0
- package/client/src/pages/deal-history.tsx +434 -0
- package/client/src/pages/deal-line-items.tsx +1703 -0
- package/client/src/pages/demo-status.tsx +113 -0
- package/client/src/pages/direct-campaign-details.tsx +361 -0
- package/client/src/pages/direct-campaigns-new.tsx +824 -0
- package/client/src/pages/dsp-form.tsx +803 -0
- package/client/src/pages/dsp-list.tsx +239 -0
- package/client/src/pages/folder-content.tsx +336 -0
- package/client/src/pages/integrations.tsx +429 -0
- package/client/src/pages/line-item-creatives.tsx +789 -0
- package/client/src/pages/line-item-detail-page.tsx +684 -0
- package/client/src/pages/line-item-form-page.tsx +3261 -0
- package/client/src/pages/line-item-wizard.tsx +1207 -0
- package/client/src/pages/login.tsx +154 -0
- package/client/src/pages/not-found.tsx +23 -0
- package/client/src/pages/proof-of-play.tsx +397 -0
- package/client/src/pages/public-approval.tsx +551 -0
- package/client/src/pages/reports.tsx +231 -0
- package/client/src/pages/settings.tsx +760 -0
- package/client/src/pages/signals.tsx +389 -0
- package/client/src/pages/tags.tsx +318 -0
- package/client/src/pages/test-results.tsx +328 -0
- package/client/src/store/hooks.ts +5 -0
- package/client/src/store/index.ts +15 -0
- package/client/src/store/mapMarkerLocationsSlice.ts +241 -0
- package/client/src/styles/design-tokens.css +324 -0
- package/client/src/test/setup.ts +261 -0
- package/client/src/test/test-utils.tsx +40 -0
- package/client/src/types/approval.ts +221 -0
- package/client/src/types/content-hub.ts +209 -0
- package/client/src/types/geofencing.ts +67 -0
- package/client/src/types/transcoding.ts +140 -0
- package/client/src/vite-env.d.ts +18 -0
- package/components.json +20 -0
- package/creative-api.json +1 -0
- package/docs/AI_REFERENCE.md +459 -0
- package/docs/MWDesign-Prompt.md +132 -0
- package/docs/MWDesign-System.md +344 -0
- package/docs/test-plan.md +277 -0
- package/e2e/AUTONOMOUS-TESTING.md +406 -0
- package/e2e/README.md +219 -0
- package/e2e/autonomous-flow.spec.ts +308 -0
- package/e2e/debug-sso.spec.ts +163 -0
- package/e2e/direct-campaigns.spec.ts +219 -0
- package/e2e/explore-sso.spec.ts +149 -0
- package/e2e/fixtures/auth.ts +26 -0
- package/e2e/fixtures/enhanced-test.ts +331 -0
- package/e2e/pagination.spec.ts +280 -0
- package/e2e/view-toggle.spec.ts +312 -0
- package/generated-icon.png +0 -0
- package/i18next-scanner.config.cjs +46 -0
- package/package.json +141 -0
- package/playwright.config.ts +93 -0
- package/postcss.config.js +6 -0
- package/replit.md +196 -0
- package/screenshot-after-login.png +0 -0
- package/screenshot-contenthub-grid.png +0 -0
- package/screenshot-contenthub-list-fixed.png +0 -0
- package/screenshot-contenthub-list.png +0 -0
- package/screenshot-create-deal.png +0 -0
- package/screenshot-dashboard.png +0 -0
- package/screenshot-deals.png +0 -0
- package/screenshot-login-filled.png +0 -0
- package/screenshot-login.png +0 -0
- package/screenshot.mjs +24 -0
- package/scripts/deploy-stg.sh +185 -0
- package/shared/direct-io-schema.ts +383 -0
- package/shared/schema.ts +439 -0
- package/shared/screen-types.ts +149 -0
- package/springdocDefault.json +1 -0
- package/swagger-ui-bundle.js +2 -0
- package/swagger-ui-init.js +10316 -0
- package/tailwind.config.ts +282 -0
- package/terraform/README.md +306 -0
- package/terraform/cloudfront.tf +289 -0
- package/terraform/ecs.tf +727 -0
- package/terraform/environments/dev.tfvars +59 -0
- package/terraform/environments/production.tfvars +60 -0
- package/terraform/main.tf +47 -0
- package/terraform/outputs.tf +145 -0
- package/terraform/s3.tf +192 -0
- package/terraform/variables.tf +226 -0
- package/terraform/waf.tf +165 -0
- package/terraform-frontend/.terraform.lock.hcl +25 -0
- package/terraform-frontend/README.md +85 -0
- package/terraform-frontend/cloudfront.tf +125 -0
- package/terraform-frontend/main.tf +31 -0
- package/terraform-frontend/outputs.tf +24 -0
- package/terraform-frontend/terraform.tfvars +12 -0
- package/terraform-frontend/variables.tf +53 -0
- package/tsconfig.json +23 -0
- package/vite.config.ts +226 -0
- package/vitest.config.ts +56 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Hub API Types
|
|
3
|
+
* Base URL: Configured via VITE_CONTENT_HUB_API_URL environment variable
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Direct Content Hub API configuration (CORS enabled)
|
|
7
|
+
export const CONTENT_HUB_CONFIG = {
|
|
8
|
+
BASE_URL: import.meta.env.VITE_CONTENT_HUB_API_URL,
|
|
9
|
+
API_PREFIX: '/api/v1/rest',
|
|
10
|
+
COMPANY_ID: '123e4567-e89b-12d3-a456-426614174000',
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
// Enums
|
|
14
|
+
export enum CreativeStatus {
|
|
15
|
+
DRAFT = 'draft',
|
|
16
|
+
APPROVED = 'approved',
|
|
17
|
+
REJECTED = 'rejected',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export enum JobStatus {
|
|
21
|
+
PENDING = 'PENDING',
|
|
22
|
+
PROCESSING = 'PROCESSING',
|
|
23
|
+
COMPLETED = 'COMPLETED',
|
|
24
|
+
FAILED = 'FAILED',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export enum CreativeType {
|
|
28
|
+
IMAGE = 'image',
|
|
29
|
+
VIDEO = 'video',
|
|
30
|
+
AUDIO = 'audio',
|
|
31
|
+
HTML5 = 'html5',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Folder Types
|
|
35
|
+
export interface Folder {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
company_id: string;
|
|
40
|
+
parent_id?: string;
|
|
41
|
+
no_of_creatives: number;
|
|
42
|
+
creatives: {
|
|
43
|
+
image?: number;
|
|
44
|
+
video?: number;
|
|
45
|
+
audio?: number;
|
|
46
|
+
html5?: number;
|
|
47
|
+
total?: number;
|
|
48
|
+
};
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface FolderCreate {
|
|
54
|
+
name: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
company_id: string;
|
|
57
|
+
parent_id?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface FolderUpdate {
|
|
61
|
+
name?: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
parent_id?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface FolderListResponse {
|
|
67
|
+
data: Folder[];
|
|
68
|
+
pagination: {
|
|
69
|
+
page: number;
|
|
70
|
+
limit: number;
|
|
71
|
+
total: number;
|
|
72
|
+
total_pages: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Creative Types
|
|
77
|
+
export interface CreativeMetadata {
|
|
78
|
+
// Image metadata
|
|
79
|
+
width?: number;
|
|
80
|
+
height?: number;
|
|
81
|
+
aspect_ratio?: string;
|
|
82
|
+
format?: string;
|
|
83
|
+
|
|
84
|
+
// Video metadata
|
|
85
|
+
duration?: number;
|
|
86
|
+
codec?: string;
|
|
87
|
+
frame_rate?: number;
|
|
88
|
+
|
|
89
|
+
// Audio metadata
|
|
90
|
+
bitrate?: number;
|
|
91
|
+
sample_rate?: number;
|
|
92
|
+
channels?: number;
|
|
93
|
+
|
|
94
|
+
// File metadata
|
|
95
|
+
file_size?: number;
|
|
96
|
+
mime_type?: string;
|
|
97
|
+
resolution?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface Creative {
|
|
101
|
+
id: string;
|
|
102
|
+
filename: string;
|
|
103
|
+
company_id?: string;
|
|
104
|
+
folder_id?: string;
|
|
105
|
+
status: string; // "approved", "rejected", "draft"
|
|
106
|
+
transcode_status?: string;
|
|
107
|
+
mime_type: string;
|
|
108
|
+
format: string;
|
|
109
|
+
size_bytes: number;
|
|
110
|
+
cdn_path: string; // This is the asset URL
|
|
111
|
+
thumbnail?: string; // This is the thumbnail URL
|
|
112
|
+
width?: number;
|
|
113
|
+
height?: number;
|
|
114
|
+
duration_seconds?: number;
|
|
115
|
+
metadata?: CreativeMetadata;
|
|
116
|
+
tags?: string[];
|
|
117
|
+
folder?: {
|
|
118
|
+
id: string;
|
|
119
|
+
name: string;
|
|
120
|
+
};
|
|
121
|
+
created_at: string;
|
|
122
|
+
updated_at?: string;
|
|
123
|
+
approved_at?: string;
|
|
124
|
+
rejected_at?: string;
|
|
125
|
+
approved_by?: string;
|
|
126
|
+
rejected_by?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface CreativeUpload {
|
|
130
|
+
file: File;
|
|
131
|
+
company_id: string;
|
|
132
|
+
folder_id?: string;
|
|
133
|
+
tags?: string[];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface CreativeApprovePayload {
|
|
137
|
+
reviewer_id: string;
|
|
138
|
+
comments?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface CreativeRejectPayload {
|
|
142
|
+
reviewer_id: string;
|
|
143
|
+
comments?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface CreativeListResponse {
|
|
147
|
+
data: Creative[];
|
|
148
|
+
pagination: {
|
|
149
|
+
page: number;
|
|
150
|
+
limit: number;
|
|
151
|
+
total: number;
|
|
152
|
+
total_pages: number;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Filter Types
|
|
157
|
+
export interface FolderFilters {
|
|
158
|
+
page?: number;
|
|
159
|
+
limit?: number;
|
|
160
|
+
company_id?: string;
|
|
161
|
+
parent_id?: string;
|
|
162
|
+
search?: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface CreativeFilters {
|
|
166
|
+
page?: number;
|
|
167
|
+
limit?: number;
|
|
168
|
+
company_id?: string;
|
|
169
|
+
folder_id?: string;
|
|
170
|
+
search?: string;
|
|
171
|
+
status?: CreativeStatus;
|
|
172
|
+
transcode_status?: JobStatus;
|
|
173
|
+
tag?: string;
|
|
174
|
+
mime_type?: string; // Supports wildcards: 'image/*', 'video/*', 'audio/*'
|
|
175
|
+
format?: string;
|
|
176
|
+
min_size_bytes?: number;
|
|
177
|
+
max_size_bytes?: number;
|
|
178
|
+
min_duration?: number;
|
|
179
|
+
max_duration?: number;
|
|
180
|
+
resolution?: string; // e.g., '1920x1080', '3840x2160'
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// API Response Types
|
|
184
|
+
export interface ApiResponse<T> {
|
|
185
|
+
status: number;
|
|
186
|
+
result: T;
|
|
187
|
+
message?: string;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface ApiError {
|
|
191
|
+
status: number;
|
|
192
|
+
error: string;
|
|
193
|
+
message?: string;
|
|
194
|
+
details?: any;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Helper type for pagination
|
|
198
|
+
export interface PaginationParams {
|
|
199
|
+
page: number;
|
|
200
|
+
limit: number;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface PaginatedResponse<T> {
|
|
204
|
+
items: T[];
|
|
205
|
+
total: number;
|
|
206
|
+
page: number;
|
|
207
|
+
limit: number;
|
|
208
|
+
total_pages: number;
|
|
209
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export interface MapGeometry {
|
|
2
|
+
type: 'Point' | 'Polygon' | 'Circle';
|
|
3
|
+
coordinates: number[] | number[][] | number[][][];
|
|
4
|
+
radius?: number;
|
|
5
|
+
poi?: string[];
|
|
6
|
+
metadata?: Record<string, string>;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MapMarkerLocation {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
latitude: number;
|
|
14
|
+
longitude: number;
|
|
15
|
+
radius?: number;
|
|
16
|
+
address?: string;
|
|
17
|
+
geometry?: MapGeometry;
|
|
18
|
+
properties?: Record<string, any>;
|
|
19
|
+
poi?: string[];
|
|
20
|
+
metadata?: Record<string, string>;
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface GeoImportFile {
|
|
25
|
+
id: string;
|
|
26
|
+
fileName: string;
|
|
27
|
+
originalName?: string;
|
|
28
|
+
countryName: string;
|
|
29
|
+
uploadedAt: string;
|
|
30
|
+
uploadedBy?: string;
|
|
31
|
+
locationCount: number;
|
|
32
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
33
|
+
errorMessage?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface GeoImportFilesParams {
|
|
37
|
+
page?: number;
|
|
38
|
+
limit?: number;
|
|
39
|
+
countryName?: string;
|
|
40
|
+
search?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface GeoImportFilesResponse {
|
|
44
|
+
files: GeoImportFile[];
|
|
45
|
+
pagination: {
|
|
46
|
+
page: number;
|
|
47
|
+
limit: number;
|
|
48
|
+
total: number;
|
|
49
|
+
totalPages: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface GeoImportLocationsResponse {
|
|
54
|
+
locations: MapMarkerLocation[];
|
|
55
|
+
total: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface UploadGeoCoordinatesResponse {
|
|
59
|
+
success: boolean;
|
|
60
|
+
file: GeoImportFile;
|
|
61
|
+
message?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface GeoImportDeleteResponse {
|
|
65
|
+
success: boolean;
|
|
66
|
+
message?: string;
|
|
67
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Transcoding types for Content Hub API
|
|
2
|
+
|
|
3
|
+
export type TranscodeProfile = "low" | "medium" | "high" | "preview" | "custom";
|
|
4
|
+
|
|
5
|
+
export type TranscodeFormat = "mp4" | "webm" | "jpeg" | "png" | "mp3" | "wav" | "mpeg";
|
|
6
|
+
|
|
7
|
+
export type JobStatus = "queued" | "running" | "completed" | "failed" | "cancelled" | "partial";
|
|
8
|
+
|
|
9
|
+
export interface TranscodeRequest {
|
|
10
|
+
profiles: TranscodeProfile[];
|
|
11
|
+
target_formats?: TranscodeFormat[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TranscodeJob {
|
|
15
|
+
profile: TranscodeProfile;
|
|
16
|
+
format: TranscodeFormat;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TranscodeResponse {
|
|
20
|
+
status: number;
|
|
21
|
+
result: {
|
|
22
|
+
creative_id: string;
|
|
23
|
+
jobs: TranscodeJob[];
|
|
24
|
+
auto_formats?: TranscodeFormat[];
|
|
25
|
+
};
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TranscodedVariant {
|
|
30
|
+
id: string;
|
|
31
|
+
creative_id: string;
|
|
32
|
+
profile: TranscodeProfile;
|
|
33
|
+
format: TranscodeFormat;
|
|
34
|
+
storage_path: string;
|
|
35
|
+
cdn_path?: string;
|
|
36
|
+
file_size_bytes?: number;
|
|
37
|
+
width?: number;
|
|
38
|
+
height?: number;
|
|
39
|
+
duration_seconds?: number;
|
|
40
|
+
bitrate?: number;
|
|
41
|
+
created_at: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface TranscodingJob {
|
|
45
|
+
id: string;
|
|
46
|
+
creative_id: string;
|
|
47
|
+
company_id: string;
|
|
48
|
+
profile: TranscodeProfile;
|
|
49
|
+
target_format: TranscodeFormat;
|
|
50
|
+
status: JobStatus;
|
|
51
|
+
progress_percent?: number;
|
|
52
|
+
error_message?: string;
|
|
53
|
+
started_at?: string;
|
|
54
|
+
completed_at?: string;
|
|
55
|
+
created_at: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface TranscodingJobsFilters {
|
|
59
|
+
creative_id?: string;
|
|
60
|
+
company_id?: string;
|
|
61
|
+
status?: JobStatus;
|
|
62
|
+
page?: number;
|
|
63
|
+
limit?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface TranscodingJobsResponse {
|
|
67
|
+
jobs: TranscodingJob[];
|
|
68
|
+
total: number;
|
|
69
|
+
page: number;
|
|
70
|
+
limit: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Profile configuration metadata
|
|
74
|
+
export interface ProfileConfig {
|
|
75
|
+
value: TranscodeProfile;
|
|
76
|
+
label: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const TRANSCODE_PROFILES: ProfileConfig[] = [
|
|
81
|
+
{
|
|
82
|
+
value: "low",
|
|
83
|
+
label: "Low Quality",
|
|
84
|
+
description: "Fast processing, smaller file sizes (good for previews)",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
value: "medium",
|
|
88
|
+
label: "Medium Quality",
|
|
89
|
+
description: "Balanced quality and file size (recommended)",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
value: "high",
|
|
93
|
+
label: "High Quality",
|
|
94
|
+
description: "Maximum quality output (larger files)",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
value: "preview",
|
|
98
|
+
label: "Preview",
|
|
99
|
+
description: "Quick low-resolution preview generation",
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
// Format suggestions based on MIME type
|
|
104
|
+
export const FORMAT_SUGGESTIONS: Record<string, TranscodeFormat[]> = {
|
|
105
|
+
"video/": ["mp4", "webm"],
|
|
106
|
+
"audio/": ["mp3", "wav"],
|
|
107
|
+
"image/": ["jpeg", "png"],
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export function getSuggestedFormats(mimeType: string): TranscodeFormat[] {
|
|
111
|
+
for (const [prefix, formats] of Object.entries(FORMAT_SUGGESTIONS)) {
|
|
112
|
+
if (mimeType.startsWith(prefix)) {
|
|
113
|
+
return formats;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getFormatLabel(format: TranscodeFormat): string {
|
|
120
|
+
return format.toUpperCase();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getJobStatusColor(
|
|
124
|
+
status: JobStatus
|
|
125
|
+
): "default" | "secondary" | "destructive" | "outline" {
|
|
126
|
+
switch (status) {
|
|
127
|
+
case "completed":
|
|
128
|
+
return "default";
|
|
129
|
+
case "running":
|
|
130
|
+
case "queued":
|
|
131
|
+
return "secondary";
|
|
132
|
+
case "failed":
|
|
133
|
+
case "cancelled":
|
|
134
|
+
return "destructive";
|
|
135
|
+
case "partial":
|
|
136
|
+
return "outline";
|
|
137
|
+
default:
|
|
138
|
+
return "outline";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
readonly VITE_INFLUENCE_DEALS_API_URL: string;
|
|
5
|
+
readonly VITE_OAUTH_API_URL: string;
|
|
6
|
+
readonly VITE_OAUTH_REDIRECT_URI: string;
|
|
7
|
+
readonly VITE_IAM_API_URL: string;
|
|
8
|
+
readonly VITE_CONTENT_HUB_API_URL: string;
|
|
9
|
+
readonly VITE_PLANNER_URL: string;
|
|
10
|
+
readonly VITE_INVENTORY_URL: string;
|
|
11
|
+
readonly VITE_MEASURE_URL: string;
|
|
12
|
+
readonly VITE_ACCOUNT_URL: string;
|
|
13
|
+
readonly VITE_INFLUENCE_URL: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ImportMeta {
|
|
17
|
+
readonly env: ImportMetaEnv;
|
|
18
|
+
}
|
package/components.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "tailwind.config.ts",
|
|
8
|
+
"css": "client/src/index.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"openapi":"3.1.0","info":{"title":"DOOH Content Hub API","description":"\n ## Digital Out-of-Home Content Hub Microservice\n \n A production-grade FastAPI microservice for managing DOOH creative assets with advanced features:\n \n ### Key Features\n * **Smart Metadata Extraction**: Automatic extraction for images, videos, audio, and HTML5 files\n * **Intelligent Auto-Transcoding**: Videos → MP4+WebM, Audio → MP3+WAV, Images → JPEG+PNG\n * **Folder Auto-Population**: Real-time statistics tracking for creative counts and summaries\n * **AWS S3 Integration**: Secure cloud storage with CDN support\n * **Comprehensive Audit Logging**: Full audit trail for all operations\n * **Approval Workflows**: Built-in creative review and approval system\n \n ### Supported File Types\n * **Images**: JPEG, PNG, GIF, WebP\n * **Videos**: MP4, WebM, WMV, AVI, MOV\n * **Audio**: MP3, WAV, AAC, OGG\n * **HTML5**: Interactive HTML5 creatives\n \n ### API Versioning\n Current Version: **v1** (prefix: `/api/v1/rest`)\n ","version":"1.0.0"},"paths":{"/api/v1/rest/folders/":{"get":{"tags":["Folders"],"summary":"List Creative Folders","description":"Retrieve a paginated list of creative folders with optional filtering.\n \n **Features:**\n - Pagination support (default: 20 items per page, max: 100)\n - Filter by company, parent folder, or search term\n - Returns folder statistics (creative counts, summaries)\n \n **Auto-Population:**\n - Each folder includes `no_of_creatives` and `creatives` summary\n - Statistics auto-update on creative upload, move, or delete","operationId":"list_folders_api_v1_rest_folders__get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (starts at 1)","default":1,"title":"Page"},"description":"Page number (starts at 1)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Limit"},"description":"Items per page (max 100)"},{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by company ID","title":"Company Id"},"description":"Filter by company ID"},{"name":"parent_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by parent folder ID","title":"Parent Id"},"description":"Filter by parent folder ID"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term for folder name or description","title":"Search"},"description":"Search term for folder name or description"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolderListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Folders"],"summary":"Create New Folder","description":"Create a new creative folder for organizing assets.\n \n **Auto-Initialization:**\n - Folder stats initialized to zero (no_of_creatives: 0)\n - Empty creative summary created automatically\n - Supports nested folder hierarchy via parent_id\n \n **Example Request:**\n ```json\n {\n \"company_id\": \"123e4567-e89b-12d3-a456-426614174000\",\n \"name\": \"E2E Test Folder\",\n \"description\": \"Real end-to-end testing\"\n }\n ```\n \n **Example Response:**\n ```json\n {\n \"status\": 201,\n \"result\": {\n \"id\": \"786a812d-42cf-484a-9cfb-66f4bdd7113b\",\n \"name\": \"E2E Test Folder\",\n \"description\": \"Real end-to-end testing\",\n \"company_id\": \"123e4567-e89b-12d3-a456-426614174000\",\n \"no_of_creatives\": 0,\n \"creatives\": {},\n \"created_at\": \"2025-11-06T04:15:00.123456\"\n },\n \"message\": \"Folder created\"\n }\n ```","operationId":"create_folder_api_v1_rest_folders__post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolderCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Folder Api V1 Rest Folders Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/folders/{folder_id}":{"get":{"tags":["Folders"],"summary":"Get Folder Details","description":"Retrieve detailed information about a specific folder.\n \n **Includes:**\n - Folder metadata (name, description, hierarchy)\n - Statistics (creative counts by status, format, total size)\n - Auto-populated creative summary","operationId":"get_folder_api_v1_rest_folders__folder_id__get","parameters":[{"name":"folder_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Folder Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Folder Api V1 Rest Folders Folder Id Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Folders"],"summary":"Update Folder","description":"Update an existing folder's properties.\n \n **Updatable Fields:**\n - Name\n - Description\n - Parent folder (to reorganize hierarchy)\n \n **Note:** Folder statistics are auto-calculated and cannot be manually updated.","operationId":"update_folder_api_v1_rest_folders__folder_id__put","parameters":[{"name":"folder_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Folder Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolderUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Folder Api V1 Rest Folders Folder Id Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Folders"],"summary":"Delete Folder","description":"Delete a folder. Folder must be empty (no creatives).\n \n **Safety:**\n - Cannot delete folders containing creatives\n - Move or delete creatives first before deleting folder","operationId":"delete_folder_api_v1_rest_folders__folder_id__delete","parameters":[{"name":"folder_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Folder Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Folder Api V1 Rest Folders Folder Id Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/":{"get":{"tags":["Creatives"],"summary":"List Creatives","description":"Retrieve paginated list of creative assets with filtering.\n \n **Query Parameters:**\n - `page` (int): Page number, default 1\n - `limit` (int): Items per page, default 20, max 100\n - `company_id` (UUID): Filter by company\n - `folder_id` (UUID): Filter by folder\n - `search` (string): Search filename\n - `status` (enum): DRAFT, APPROVED, REJECTED\n - `transcode_status` (enum): Filter by transcoding status\n - `tag` (string): Filter by tag\n - `mime_type` (string): MIME type filter, supports wildcards (e.g., `image/*`, `video/*`)\n - `format` (string): File format (e.g., `mp4`, `jpeg`)\n - `min_size_bytes`, `max_size_bytes` (int): File size range\n - `min_duration`, `max_duration` (int): Duration range in seconds\n - `resolution` (string): Resolution filter (e.g., `1920x1080`)\n \n **Response:** Includes pagination metadata and creative list with auto-extracted metadata (duration, dimensions, codec, etc.)","operationId":"list_creatives_api_v1_rest_creatives__get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (starts at 1)","default":1,"title":"Page"},"description":"Page number (starts at 1)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Limit"},"description":"Items per page (max 100)"},{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by company ID","title":"Company Id"},"description":"Filter by company ID"},{"name":"folder_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by folder ID","title":"Folder Id"},"description":"Filter by folder ID"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term for filename","title":"Search"},"description":"Search term for filename"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CreativeStatus"},{"type":"null"}],"description":"Filter by creative status (DRAFT, APPROVED, REJECTED)","title":"Status"},"description":"Filter by creative status (DRAFT, APPROVED, REJECTED)"},{"name":"transcode_status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/JobStatus"},{"type":"null"}],"description":"Filter by transcoding status","title":"Transcode Status"},"description":"Filter by transcoding status"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag","title":"Tag"},"description":"Filter by tag"},{"name":"mime_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by MIME type (e.g., 'image/jpeg', 'video/mp4'). Supports wildcards: 'image/*', 'video/*', 'audio/*'","title":"Mime Type"},"description":"Filter by MIME type (e.g., 'image/jpeg', 'video/mp4'). Supports wildcards: 'image/*', 'video/*', 'audio/*'"},{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by file format (e.g., 'jpeg', 'mp4', 'png')","title":"Format"},"description":"Filter by file format (e.g., 'jpeg', 'mp4', 'png')"},{"name":"min_size_bytes","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Minimum file size in bytes","title":"Min Size Bytes"},"description":"Minimum file size in bytes"},{"name":"max_size_bytes","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Maximum file size in bytes","title":"Max Size Bytes"},"description":"Maximum file size in bytes"},{"name":"min_duration","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Minimum duration in seconds","title":"Min Duration"},"description":"Minimum duration in seconds"},{"name":"max_duration","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Maximum duration in seconds","title":"Max Duration"},"description":"Maximum duration in seconds"},{"name":"resolution","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by resolution (e.g., '1920x1080', '1280x720', '3840x2160')","title":"Resolution"},"description":"Filter by resolution (e.g., '1920x1080', '1280x720', '3840x2160')"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreativeListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Creatives"],"summary":"Upload Creative Asset","description":"Upload creative file with automatic metadata extraction and S3 storage.\n \n **Form Data (multipart/form-data):**\n - `file` (required): Creative file\n - `company_id` (UUID): Company ID\n - `folder_id` (UUID): Folder ID\n - `external_ref` (string): External reference\n - `tags` (string): Comma-separated tags\n \n **Response (201 Created):**\n ```json\n {\n \"status\": 201,\n \"result\": {\n \"id\": \"3d31d5e2-5b8e-42f6-88f7-7100dfde71df\",\n \"filename\": \"video.mp4\",\n \"created_at\": \"2025-11-06T04:15:12.345678\"\n },\n \"message\": \"Creative uploaded successfully\"\n }\n ```\n \n **Auto-Processing:** Metadata extraction, S3 upload, thumbnail generation, folder stats update, audit logging\n \n **Supported Formats:** JPEG, PNG, GIF, WebP, MP4, WebM, WMV, AVI, MOV, MP3, WAV, AAC, OGG, HTML5\n \n **Error Codes:**\n - `400` - Invalid file type\n - `404` - Folder not found\n - `413` - File too large\n - `422` - Validation error","operationId":"upload_creative_api_v1_rest_creatives__post","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_creative_api_v1_rest_creatives__post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload Creative Api V1 Rest Creatives Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/from-url":{"post":{"tags":["Creatives"],"summary":"Create Creative from URL","description":"Create creative from URL with asynchronous metadata extraction. Returns immediately (HTTP 202) while metadata extraction happens in background.\n \n **Request Body:**\n ```json\n {\n \"url\": \"https://cdn.example.com/video.mp4\",\n \"filename\": \"video.mp4\",\n \"company_id\": \"uuid\",\n \"folder_id\": \"uuid\",\n \"external_ref\": \"ref123\",\n \"tags\": [\"tag1\", \"tag2\"]\n }\n ```\n \n **Required:** `url`, `filename` \n **Optional:** `company_id`, `folder_id`, `external_ref`, `tags`, `mime_type`, `width`, `height`, `duration_seconds`\n \n **Response (202 Accepted):**\n ```json\n {\n \"status\": 202,\n \"result\": {\n \"id\": \"22607bac-47b3-4dcc-b75c-08fd0b649825\",\n \"filename\": \"video.mp4\",\n \"processing_status\": \"pending\",\n \"created_at\": \"2025-11-07T16:10:30.421147\"\n },\n \"message\": \"Creative created successfully. Metadata extraction in progress.\"\n }\n ```\n \n **Metadata Extraction:** Automatically extracts duration, dimensions, codec, bitrate for videos/audio, and dimensions for images. Poll `GET /creatives/{id}` to check when `processing_status` changes to \"completed\".\n \n **Security:** SSRF protection blocks private IPs (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local, multicast). Max 3 redirects, 100MB file size limit, 30s timeout.\n \n **Supported Formats:** MP4, WebM, WMV, AVI, MOV, MP3, WAV, AAC, OGG, JPEG, PNG, GIF, WebP, HTML5\n \n **Error Codes:**\n - `400` - Invalid URL scheme or private IP detected\n - `404` - Folder not found\n - `413` - File exceeds 100MB\n - `422` - Invalid request data\n - `502` - Failed to download from URL","operationId":"create_creative_from_url_api_v1_rest_creatives_from_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreativeURLCreate"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Creative From Url Api V1 Rest Creatives From Url Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}":{"put":{"tags":["Creatives"],"summary":"Update Creative","description":"Update creative properties with automatic audit logging and folder stats refresh.\n \n **Updatable Fields:**\n - Folder ID (moves creative, updates both folder statistics)\n - Tags\n - External reference\n \n **Auto-Processing:**\n - Creates audit log entry\n - Updates folder statistics if folder changes\n - Maintains version history","operationId":"update_creative_api_v1_rest_creatives__creative_id__put","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}},{"name":"performer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"ID of user performing the update","title":"Performer Id"},"description":"ID of user performing the update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreativeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Creative Api V1 Rest Creatives Creative Id Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Creatives"],"summary":"Get Creative Details","description":"Retrieve detailed information about a specific creative asset.\n \n **Includes:**\n - Full metadata from auto-extraction\n - Storage paths (S3 and CDN)\n - Transcoding status and variants\n - File integrity checksums\n - Tags and version information","operationId":"get_creative_api_v1_rest_creatives__creative_id__get","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreativeDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Creatives"],"summary":"Delete Creative","description":"Permanently delete a creative asset with automatic cleanup.\n \n **Auto-Processing:**\n - Deletes file from S3 storage\n - Removes all transcoded variants\n - Creates audit log entry\n - Updates parent folder statistics\n - Cleans up all related database records\n \n **Warning:** This action cannot be undone!","operationId":"delete_creative_api_v1_rest_creatives__creative_id__delete","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}},{"name":"performer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"ID of user performing deletion","title":"Performer Id"},"description":"ID of user performing deletion"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Creative Api V1 Rest Creatives Creative Id Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/audit":{"get":{"tags":["Creatives"],"summary":"Get Audit Logs","description":"Retrieve complete audit trail for a creative asset.\n \n **Logged Actions:**\n - CREATE: Initial upload\n - UPDATE: Property modifications\n - DELETE: Asset removal\n - TRANSCODE: Transcoding requests\n - APPROVE: Creative approval\n - REJECT: Creative rejection\n \n **Each Entry Includes:**\n - Action type and timestamp\n - Performer ID (who performed the action)\n - Change details (JSON payload)","operationId":"get_creative_audit_logs_api_v1_rest_creatives__creative_id__audit_get","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogResponse"},"title":"Response Get Creative Audit Logs Api V1 Rest Creatives Creative Id Audit Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/transcode":{"post":{"tags":["Creatives"],"summary":"Initiate Transcoding","description":"Initiate intelligent transcoding for a creative asset.\n \n **Smart Auto-Format Selection:**\n If `target_formats` is not specified, the system automatically selects optimal formats:\n - **Videos** → MP4 + WebM (web-optimized delivery)\n - **Audio** → MP3 (universal compatibility)\n - **Images** → JPEG + PNG (web formats)\n \n **Example Request (Auto-Format for Video):**\n ```\n POST /api/v1/rest/creatives/140f4a7d-2f1b-42cf-8953-a358fc4b18ae/transcode\n ```\n ```json\n {\n \"profiles\": [\"medium\"]\n }\n ```\n \n **Example Request (Multiple Profiles with Custom Formats):**\n ```\n POST /api/v1/rest/creatives/140f4a7d-2f1b-42cf-8953-a358fc4b18ae/transcode\n ```\n ```json\n {\n \"profiles\": [\"high\", \"preview\"],\n \"target_formats\": [\"mp4\", \"webm\"]\n }\n ```\n \n **Example Response (creates one job per profile × format combination):**\n ```json\n {\n \"status\": 200,\n \"result\": {\n \"creative_id\": \"140f4a7d-2f1b-42cf-8953-a358fc4b18ae\",\n \"jobs\": [\n {\"profile\": \"high\", \"format\": \"mp4\"},\n {\"profile\": \"high\", \"format\": \"webm\"},\n {\"profile\": \"preview\", \"format\": \"mp4\"},\n {\"profile\": \"preview\", \"format\": \"webm\"}\n ],\n \"auto_formats\": [\"mp4\", \"webm\"]\n },\n \"message\": \"Transcoding jobs initiated\"\n }\n ```\n \n **Note:** With 2 profiles × 2 formats = 4 jobs created\n \n **Quality Profiles:**\n - LOW: Fast processing, smaller file size\n - MEDIUM: Balanced quality and size\n - HIGH: Maximum quality\n - PREVIEW: Quick low-res preview\n - CUSTOM: User-defined settings\n \n **Manual Override:**\n Specify `target_formats` array to override auto-selection.\n Supported: mp4, webm, jpeg, png, mp3, wav, mpeg\n \n **Auto-Processing:**\n - Creates transcoding jobs for background worker\n - Supports multiple profiles simultaneously\n - Creates audit log entry","operationId":"initiate_transcode_api_v1_rest_creatives__creative_id__transcode_post","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}},{"name":"performer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"ID of user initiating transcode","title":"Performer Id"},"description":"ID of user initiating transcode"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Initiate Transcode Api V1 Rest Creatives Creative Id Transcode Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/transcodes":{"get":{"tags":["Creatives"],"summary":"Get Transcoded Files","description":"Retrieve all transcoded variants of a creative asset.\n \n **Returns:**\n - List of all successfully transcoded files\n - Each entry includes format, profile, storage paths, and file size\n - Only COMPLETED transcodes are returned","operationId":"get_transcoded_files_api_v1_rest_creatives__creative_id__transcodes_get","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TranscodedFileResponse"},"title":"Response Get Transcoded Files Api V1 Rest Creatives Creative Id Transcodes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/transcoded-files":{"get":{"tags":["Creatives"],"summary":"Get Transcoded Files (Alias)","description":"Alias for /transcodes endpoint","operationId":"get_transcoded_files_alias_api_v1_rest_creatives__creative_id__transcoded_files_get","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TranscodedFileResponse"},"title":"Response Get Transcoded Files Alias Api V1 Rest Creatives Creative Id Transcoded Files Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/approve":{"post":{"tags":["Creatives"],"summary":"Approve Creative","description":"Approve a creative asset as part of the review workflow.\n \n **Workflow:**\n - Updates creative status to APPROVED\n - Creates review record with reviewer ID and comments\n - Creates audit log entry\n - Optional: Add reviewer comments\n \n **Use Case:**\n Quality control and approval workflows for DOOH content before deployment.","operationId":"approve_creative_api_v1_rest_creatives__creative_id__approve_post","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Approve Creative Api V1 Rest Creatives Creative Id Approve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/creatives/{creative_id}/reject":{"post":{"tags":["Creatives"],"summary":"Reject Creative","description":"Reject a creative asset as part of the review workflow.\n \n **Workflow:**\n - Updates creative status to REJECTED\n - Creates review record with reviewer ID and rejection reason\n - Creates audit log entry\n - Requires comments explaining rejection reason\n \n **Use Case:**\n Quality control workflow when content doesn't meet requirements.\n Rejection comments guide content creators on necessary changes.","operationId":"reject_creative_api_v1_rest_creatives__creative_id__reject_post","parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Creative Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reject Creative Api V1 Rest Creatives Creative Id Reject Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rest/transcoding/jobs/":{"get":{"tags":["Transcoding Jobs"],"summary":"List Transcoding Jobs","operationId":"list_transcoding_jobs_api_v1_rest_transcoding_jobs__get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"creative_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Creative Id"}},{"name":"company_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/JobStatus"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscodingJobListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health","description":"Enhanced health check endpoint with comprehensive system statistics.\n\nReturns:\n- status: Application health status (UP/DOWN)\n- uptime: How long the application has been running\n- timestamp: Current server time\n- system: CPU, memory, and disk usage statistics\n- database: Database connectivity status\n- worker: Transcoding worker status","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}}},"components":{"schemas":{"ActionType":{"type":"string","enum":["create","update","delete","approve","reject","transcode","publish"],"title":"ActionType"},"ApproveRejectRequest":{"properties":{"reviewer_id":{"type":"string","format":"uuid","title":"Reviewer Id"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"}},"type":"object","required":["reviewer_id"],"title":"ApproveRejectRequest"},"AuditLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"creative_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Creative Id"},"entity_type":{"type":"string","title":"Entity Type"},"entity_id":{"type":"string","format":"uuid","title":"Entity Id"},"action":{"$ref":"#/components/schemas/ActionType"},"performed_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Performed By"},"details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Details"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","creative_id","entity_type","entity_id","action","performed_by","details","created_at"],"title":"AuditLogResponse"},"Body_upload_creative_api_v1_rest_creatives__post":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"Creative file to upload"},"company_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id","description":"Company ID (optional)"},"folder_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Folder Id","description":"Folder ID for organization"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref","description":"External reference ID"},"tags":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags","description":"Comma-separated tags"}},"type":"object","required":["file"],"title":"Body_upload_creative_api_v1_rest_creatives__post"},"CreativeDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"company_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id"},"uploader_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Uploader Id"},"folder_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Folder Id"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"},"storage_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Storage Path"},"cdn_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cdn Path"},"thumbnail":{"type":"string","title":"Thumbnail"},"filename":{"type":"string","title":"Filename"},"format":{"type":"string","title":"Format"},"mime_type":{"type":"string","title":"Mime Type"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"aspect_ratio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Aspect Ratio"},"codec":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Codec"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"status":{"$ref":"#/components/schemas/CreativeStatus"},"transcode_status":{"$ref":"#/components/schemas/JobStatus"},"validation_errors":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Validation Errors"},"meta":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Meta"},"transcoded_variants":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Transcoded Variants"},"version":{"type":"integer","title":"Version"},"checksum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checksum"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","company_id","uploader_id","folder_id","external_ref","storage_path","cdn_path","thumbnail","filename","format","mime_type","duration_seconds","width","height","aspect_ratio","codec","size_bytes","status","transcode_status","validation_errors","meta","transcoded_variants","version","checksum","tags","created_at","updated_at"],"title":"CreativeDetailResponse"},"CreativeListResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CreativeResponse"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}},"type":"object","required":["data","pagination"],"title":"CreativeListResponse"},"CreativeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"type":"string","title":"Filename"},"format":{"type":"string","title":"Format"},"mime_type":{"type":"string","title":"Mime Type"},"thumbnail":{"type":"string","title":"Thumbnail"},"cdn_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cdn Path"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"status":{"$ref":"#/components/schemas/CreativeStatus"},"transcode_status":{"$ref":"#/components/schemas/JobStatus"},"transcoded_variants":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Transcoded Variants"},"folder":{"anyOf":[{"$ref":"#/components/schemas/FolderInfo"},{"type":"null"}]},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","filename","format","mime_type","thumbnail","cdn_path","duration_seconds","width","height","size_bytes","status","transcode_status","transcoded_variants","folder","tags","created_at"],"title":"CreativeResponse"},"CreativeStatus":{"type":"string","enum":["draft","pending_approval","processing","accepted","inadequate","approved","rejected","archived"],"title":"CreativeStatus"},"CreativeURLCreate":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Url"},"filename":{"type":"string","title":"Filename"},"company_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id"},"folder_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Folder Id"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"}},"type":"object","required":["url","filename"],"title":"CreativeURLCreate","description":"Schema for creating a creative from URL with automatic metadata extraction."},"CreativeUpdate":{"properties":{"folder_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Folder Id"},"tags":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},"type":"object","title":"CreativeUpdate"},"CreativesCount":{"properties":{"image":{"type":"integer","title":"Image","default":0},"video":{"type":"integer","title":"Video","default":0},"audio":{"type":"integer","title":"Audio","default":0},"others":{"type":"integer","title":"Others","default":0}},"type":"object","title":"CreativesCount"},"FolderCreate":{"properties":{"company_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id"},"name":{"type":"string","minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["name"],"title":"FolderCreate"},"FolderInfo":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"FolderInfo"},"FolderListResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/FolderResponse"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}},"type":"object","required":["data","pagination"],"title":"FolderListResponse"},"FolderResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id"},"no_of_creatives":{"type":"integer","title":"No Of Creatives"},"creatives":{"$ref":"#/components/schemas/CreativesCount"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","description","parent_id","no_of_creatives","creatives","created_at","updated_at"],"title":"FolderResponse"},"FolderUpdate":{"properties":{"name":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id"}},"type":"object","title":"FolderUpdate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobStatus":{"type":"string","enum":["none","queued","running","completed","failed","cancelled","partial"],"title":"JobStatus"},"PaginationResponse":{"properties":{"page":{"type":"integer","title":"Page"},"limit":{"type":"integer","title":"Limit"},"total":{"type":"integer","title":"Total"},"pages":{"type":"integer","title":"Pages"}},"type":"object","required":["page","limit","total","pages"],"title":"PaginationResponse"},"TranscodeProfile":{"type":"string","enum":["low","medium","high","preview","custom"],"title":"TranscodeProfile"},"TranscodeRequest":{"properties":{"profiles":{"items":{"$ref":"#/components/schemas/TranscodeProfile"},"type":"array","title":"Profiles"},"target_formats":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Target Formats"}},"type":"object","required":["profiles"],"title":"TranscodeRequest"},"TranscodedFileResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"creative_id":{"type":"string","format":"uuid","title":"Creative Id"},"profile":{"$ref":"#/components/schemas/TranscodeProfile"},"output_path":{"type":"string","title":"Output Path"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"bitrate":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bitrate"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"checksum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checksum"},"status":{"$ref":"#/components/schemas/JobStatus"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","creative_id","profile","output_path","mime_type","format","width","height","bitrate","duration_seconds","size_bytes","checksum","status","metadata","created_at","updated_at"],"title":"TranscodedFileResponse"},"TranscodingJobListResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TranscodingJobResponse"},"type":"array","title":"Data"},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}},"type":"object","required":["data","pagination"],"title":"TranscodingJobListResponse"},"TranscodingJobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"creative_id":{"type":"string","format":"uuid","title":"Creative Id"},"company_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Company Id"},"profile":{"$ref":"#/components/schemas/TranscodeProfile"},"input_path":{"type":"string","title":"Input Path"},"output_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Path"},"target_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Format"},"status":{"$ref":"#/components/schemas/JobStatus"},"logs":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logs"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"attempts":{"type":"integer","title":"Attempts"},"output_file_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Output File Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","creative_id","company_id","profile","input_path","output_path","target_format","status","logs","error_message","started_at","finished_at","attempts","output_file_id","created_at","updated_at"],"title":"TranscodingJobResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}
|