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
package/package.json
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adserver-dashboard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.0.0"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "vite --host 0.0.0.0 --port 5000",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"preview": "vite preview --host 0.0.0.0 --port 5000",
|
|
13
|
+
"check": "tsc",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"test:coverage": "vitest run --coverage",
|
|
17
|
+
"test:results": "mkdir -p client/public/test-results && vitest run --reporter=json --outputFile=client/public/test-results/results.json || true",
|
|
18
|
+
"test:ui": "vitest --ui",
|
|
19
|
+
"test:e2e": "playwright test",
|
|
20
|
+
"test:e2e:ui": "playwright test --ui",
|
|
21
|
+
"test:e2e:headed": "playwright test --headed",
|
|
22
|
+
"test:e2e:debug": "playwright test --debug",
|
|
23
|
+
"playwright:install": "playwright install chromium",
|
|
24
|
+
"playwright:report": "playwright show-report",
|
|
25
|
+
"i18n:scan": "i18next-scanner --config i18next-scanner.config.cjs"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@hookform/resolvers": "^3.10.0",
|
|
29
|
+
"@jridgewell/trace-mapping": "^0.3.25",
|
|
30
|
+
"@mapbox/mapbox-gl-draw": "^1.5.0",
|
|
31
|
+
"@mapbox/mapbox-gl-geocoder": "^5.1.2",
|
|
32
|
+
"@moving-walls/design-system": "^1.0.11",
|
|
33
|
+
"@radix-ui/react-accordion": "^1.2.4",
|
|
34
|
+
"@radix-ui/react-alert-dialog": "^1.1.7",
|
|
35
|
+
"@radix-ui/react-aspect-ratio": "^1.1.3",
|
|
36
|
+
"@radix-ui/react-avatar": "^1.1.4",
|
|
37
|
+
"@radix-ui/react-checkbox": "^1.1.5",
|
|
38
|
+
"@radix-ui/react-collapsible": "^1.1.4",
|
|
39
|
+
"@radix-ui/react-context-menu": "^2.2.7",
|
|
40
|
+
"@radix-ui/react-dialog": "^1.1.7",
|
|
41
|
+
"@radix-ui/react-dropdown-menu": "^2.1.7",
|
|
42
|
+
"@radix-ui/react-hover-card": "^1.1.7",
|
|
43
|
+
"@radix-ui/react-label": "^2.1.3",
|
|
44
|
+
"@radix-ui/react-menubar": "^1.1.7",
|
|
45
|
+
"@radix-ui/react-navigation-menu": "^1.2.6",
|
|
46
|
+
"@radix-ui/react-popover": "^1.1.7",
|
|
47
|
+
"@radix-ui/react-progress": "^1.1.3",
|
|
48
|
+
"@radix-ui/react-radio-group": "^1.2.4",
|
|
49
|
+
"@radix-ui/react-scroll-area": "^1.2.4",
|
|
50
|
+
"@radix-ui/react-select": "^2.1.7",
|
|
51
|
+
"@radix-ui/react-separator": "^1.1.3",
|
|
52
|
+
"@radix-ui/react-slider": "^1.2.4",
|
|
53
|
+
"@radix-ui/react-slot": "^1.2.0",
|
|
54
|
+
"@radix-ui/react-switch": "^1.1.4",
|
|
55
|
+
"@radix-ui/react-tabs": "^1.1.4",
|
|
56
|
+
"@radix-ui/react-toast": "^1.2.7",
|
|
57
|
+
"@radix-ui/react-toggle": "^1.1.3",
|
|
58
|
+
"@radix-ui/react-toggle-group": "^1.1.3",
|
|
59
|
+
"@radix-ui/react-tooltip": "^1.2.0",
|
|
60
|
+
"@reduxjs/toolkit": "^2.11.2",
|
|
61
|
+
"@sentry/react": "^10.32.1",
|
|
62
|
+
"@tanstack/react-query": "^5.60.5",
|
|
63
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
64
|
+
"@testing-library/react": "^16.3.1",
|
|
65
|
+
"@testing-library/user-event": "^14.6.1",
|
|
66
|
+
"@tolgee/react": "^6.2.7",
|
|
67
|
+
"@types/leaflet": "^1.9.21",
|
|
68
|
+
"@types/mapbox__mapbox-gl-draw": "^1.4.9",
|
|
69
|
+
"@types/papaparse": "^5.5.2",
|
|
70
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
71
|
+
"@vitest/ui": "^4.0.16",
|
|
72
|
+
"ag-grid-react": "^35.0.1",
|
|
73
|
+
"class-variance-authority": "^0.7.1",
|
|
74
|
+
"clsx": "^2.1.1",
|
|
75
|
+
"cmdk": "^1.1.1",
|
|
76
|
+
"date-fns": "^3.6.0",
|
|
77
|
+
"embla-carousel-react": "^8.6.0",
|
|
78
|
+
"form-data": "^4.0.4",
|
|
79
|
+
"framer-motion": "^11.13.1",
|
|
80
|
+
"i18next": "^25.7.3",
|
|
81
|
+
"i18next-browser-languagedetector": "^8.2.0",
|
|
82
|
+
"i18next-http-backend": "^3.0.2",
|
|
83
|
+
"input-otp": "^1.4.2",
|
|
84
|
+
"jsdom": "^27.4.0",
|
|
85
|
+
"leaflet": "^1.9.4",
|
|
86
|
+
"lucide-react": "^0.453.0",
|
|
87
|
+
"mapbox-gl": "^3.16.0",
|
|
88
|
+
"mapbox-gl-draw-circle": "^1.1.2",
|
|
89
|
+
"mapbox-gl-draw-rectangle-mode": "^1.0.4",
|
|
90
|
+
"next-themes": "^0.4.6",
|
|
91
|
+
"papaparse": "^5.5.3",
|
|
92
|
+
"react": "^18.3.1",
|
|
93
|
+
"react-day-picker": "^8.10.1",
|
|
94
|
+
"react-dom": "^18.3.1",
|
|
95
|
+
"react-hook-form": "^7.55.0",
|
|
96
|
+
"react-i18next": "^16.5.1",
|
|
97
|
+
"react-icons": "^5.4.0",
|
|
98
|
+
"react-leaflet": "^4.2.1",
|
|
99
|
+
"react-markdown": "^10.1.0",
|
|
100
|
+
"react-redux": "^9.2.0",
|
|
101
|
+
"react-resizable-panels": "^2.1.7",
|
|
102
|
+
"recharts": "^2.15.2",
|
|
103
|
+
"remark-gfm": "^4.0.1",
|
|
104
|
+
"tailwind-merge": "^2.6.0",
|
|
105
|
+
"tailwindcss-animate": "^1.0.7",
|
|
106
|
+
"tw-animate-css": "^1.2.5",
|
|
107
|
+
"vaul": "^1.1.2",
|
|
108
|
+
"vitest": "^4.0.16",
|
|
109
|
+
"wouter": "^3.3.5",
|
|
110
|
+
"zod": "^3.24.2",
|
|
111
|
+
"zod-validation-error": "^3.4.0"
|
|
112
|
+
},
|
|
113
|
+
"devDependencies": {
|
|
114
|
+
"@playwright/test": "^1.57.0",
|
|
115
|
+
"@replit/vite-plugin-cartographer": "^0.4.4",
|
|
116
|
+
"@replit/vite-plugin-dev-banner": "^0.1.1",
|
|
117
|
+
"@replit/vite-plugin-runtime-error-modal": "^0.0.3",
|
|
118
|
+
"@tailwindcss/typography": "^0.5.15",
|
|
119
|
+
"@tailwindcss/vite": "^4.1.3",
|
|
120
|
+
"@types/node": "20.16.11",
|
|
121
|
+
"@types/react": "^18.3.11",
|
|
122
|
+
"@types/react-dom": "^18.3.1",
|
|
123
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
124
|
+
"autoprefixer": "^10.4.20",
|
|
125
|
+
"dotenv": "^17.2.3",
|
|
126
|
+
"i18next-scanner": "^4.6.0",
|
|
127
|
+
"postcss": "^8.4.47",
|
|
128
|
+
"tailwindcss": "^3.4.17",
|
|
129
|
+
"typescript": "5.6.3",
|
|
130
|
+
"vite": "^5.4.20",
|
|
131
|
+
"vite-plugin-pwa": "^1.2.0",
|
|
132
|
+
"workbox-window": "^7.4.0"
|
|
133
|
+
},
|
|
134
|
+
"optionalDependencies": {
|
|
135
|
+
"bufferutil": "^4.0.8"
|
|
136
|
+
},
|
|
137
|
+
"overrides": {
|
|
138
|
+
"minimist": "^1.2.8",
|
|
139
|
+
"underscore": "^1.13.6"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
2
|
+
import * as dotenv from 'dotenv';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
// Get __dirname equivalent in ESM
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
// Load .env.test file
|
|
11
|
+
dotenv.config({ path: path.resolve(__dirname, '.env.test') });
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Playwright Configuration for Local Development Testing
|
|
15
|
+
*
|
|
16
|
+
* This configuration is designed for local testing only.
|
|
17
|
+
* The frontend is deployed as a static site in CI/CD, so these tests
|
|
18
|
+
* are not part of the deployment pipeline.
|
|
19
|
+
*/
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
testDir: './e2e',
|
|
22
|
+
|
|
23
|
+
// Maximum time one test can run for
|
|
24
|
+
timeout: 30 * 1000,
|
|
25
|
+
|
|
26
|
+
// Run tests in files in parallel
|
|
27
|
+
fullyParallel: true,
|
|
28
|
+
|
|
29
|
+
// Fail the build on CI if you accidentally left test.only in the source code
|
|
30
|
+
forbidOnly: !!process.env.CI,
|
|
31
|
+
|
|
32
|
+
// Retry on CI only
|
|
33
|
+
retries: process.env.CI ? 2 : 0,
|
|
34
|
+
|
|
35
|
+
// Opt out of parallel tests on CI
|
|
36
|
+
workers: process.env.CI ? 1 : undefined,
|
|
37
|
+
|
|
38
|
+
// Reporter to use
|
|
39
|
+
reporter: 'html',
|
|
40
|
+
|
|
41
|
+
// Shared settings for all the projects below
|
|
42
|
+
use: {
|
|
43
|
+
// Base URL to use in actions like `await page.goto('/')`
|
|
44
|
+
baseURL: 'http://localhost:5000',
|
|
45
|
+
|
|
46
|
+
// Collect trace when retrying the failed test
|
|
47
|
+
trace: 'on-first-retry',
|
|
48
|
+
|
|
49
|
+
// Screenshot on failure
|
|
50
|
+
screenshot: 'only-on-failure',
|
|
51
|
+
|
|
52
|
+
// Video on failure
|
|
53
|
+
video: 'retain-on-failure',
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// Configure projects for major browsers
|
|
57
|
+
projects: [
|
|
58
|
+
{
|
|
59
|
+
name: 'chromium',
|
|
60
|
+
use: { ...devices['Desktop Chrome'] },
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
// Uncomment to test on Firefox
|
|
64
|
+
// {
|
|
65
|
+
// name: 'firefox',
|
|
66
|
+
// use: { ...devices['Desktop Firefox'] },
|
|
67
|
+
// },
|
|
68
|
+
|
|
69
|
+
// Uncomment to test on WebKit (Safari)
|
|
70
|
+
// {
|
|
71
|
+
// name: 'webkit',
|
|
72
|
+
// use: { ...devices['Desktop Safari'] },
|
|
73
|
+
// },
|
|
74
|
+
|
|
75
|
+
// Uncomment to test mobile viewports
|
|
76
|
+
// {
|
|
77
|
+
// name: 'Mobile Chrome',
|
|
78
|
+
// use: { ...devices['Pixel 5'] },
|
|
79
|
+
// },
|
|
80
|
+
// {
|
|
81
|
+
// name: 'Mobile Safari',
|
|
82
|
+
// use: { ...devices['iPhone 12'] },
|
|
83
|
+
// },
|
|
84
|
+
],
|
|
85
|
+
|
|
86
|
+
// Run your local dev server before starting the tests
|
|
87
|
+
webServer: {
|
|
88
|
+
command: 'npm run dev',
|
|
89
|
+
url: 'http://localhost:5000',
|
|
90
|
+
reuseExistingServer: !process.env.CI,
|
|
91
|
+
timeout: 120 * 1000,
|
|
92
|
+
},
|
|
93
|
+
});
|
package/replit.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Ad Server Platform
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Ad Server Platform is a comprehensive digital advertising solution designed for managing campaigns, screens, creatives, and ad delivery. It offers real-time analytics and geofencing capabilities. The platform aims to streamline ad operations, provide robust reporting, and enable precise targeting for advertisers, enhancing the efficiency and effectiveness of digital out-of-home (DOOH) advertising.
|
|
6
|
+
|
|
7
|
+
## User Preferences
|
|
8
|
+
|
|
9
|
+
Preferred communication style: Simple, everyday language.
|
|
10
|
+
|
|
11
|
+
## Demo Status / Changes Log
|
|
12
|
+
|
|
13
|
+
### Recent Changes (Week of Feb 10–17, 2026)
|
|
14
|
+
|
|
15
|
+
#### Line Item Form - API Payload Cleanup
|
|
16
|
+
- Removed `unlimitedBudget` toggle (UI-only, not in API schema)
|
|
17
|
+
- Removed `signalEnabled` field from payload and UI (not supported by API)
|
|
18
|
+
- Removed generic Signals section (signalId/signalName) — API uses structured signal format
|
|
19
|
+
- Removed `automatedBidding` toggle from Bid Strategy section (not in API schema)
|
|
20
|
+
- Removed Billing section (billable/non-billable) from line item form (handled at deal level)
|
|
21
|
+
- Added `frequencyCap`, `trafficAllocation`, `inventorySource` to line item API payload and builder functions
|
|
22
|
+
- `deliveryTargeting` restricted to DIRECT deals only (API rejects it for PROGRAMMATIC)
|
|
23
|
+
|
|
24
|
+
#### Line Item Form - Weather Signals (DIRECT only)
|
|
25
|
+
- New "Delivery Signals" section with weather targeting matching API format
|
|
26
|
+
- Weather conditions grid: Sunny, Partly Cloudy, Cloudy, Rainy, Stormy, Snowy, Windy, Foggy, Hazy
|
|
27
|
+
- Temperature range: min/max with Celsius/Fahrenheit unit selector
|
|
28
|
+
- Payload format: `deliveryTargeting.signals.weather.conditions[]` + `temperature{min,max,unit}`
|
|
29
|
+
- Section hidden for PROGRAMMATIC deals
|
|
30
|
+
|
|
31
|
+
#### Line Item Form - Geofencing Fix
|
|
32
|
+
- Geofencing payload now sends `lat` and `lng` (required by API), not just location name
|
|
33
|
+
- Handles Point geometries (search/geocoding) and Polygon geometries (drawn areas via centroid)
|
|
34
|
+
- Edit mode properly restores `geoLocations` state from existing line item data
|
|
35
|
+
|
|
36
|
+
#### Line Item Form - Targeting Sections (Side Popover Pattern)
|
|
37
|
+
- SSP/Exchange, Inventory Type, Media Owner, Inventory Format all use consistent Sheet (side popover) pattern
|
|
38
|
+
- Replaced inline Collapsible with Sheet drawers for all targeting sections
|
|
39
|
+
- Venue Type uses recursive tree with unlimited hierarchy depth (API-driven)
|
|
40
|
+
- Real API integrations for companies (`/api/v1/companies?is_ssp=true`), inventory types (`/api/v1/inventory-types`), inventory display formats (`/api/v1/inventory-display-formats`)
|
|
41
|
+
- API queries only fire when drawer is open (`enabled: isSheetOpen`)
|
|
42
|
+
|
|
43
|
+
#### Deal Creation Page
|
|
44
|
+
- Removed description field from programmatic deal creation
|
|
45
|
+
- Removed seller field from deal list and filters
|
|
46
|
+
- Fixed impression multiplier type handling in deal creation payloads
|
|
47
|
+
- Updated deal creation form titles and field arrangements
|
|
48
|
+
- Removed status dropdown from deal creation page
|
|
49
|
+
|
|
50
|
+
#### Line Item Form - Other Improvements
|
|
51
|
+
- Added priority field to line item API payload
|
|
52
|
+
- Custom fees included in line item creation payload
|
|
53
|
+
- Geography map opens directly by clicking the row
|
|
54
|
+
- Form validation errors shown to user on save
|
|
55
|
+
- Bid Strategy and Auction Type hidden for traditional deals
|
|
56
|
+
- Scroll-aware tips in sidebar
|
|
57
|
+
- Form insights section improvements
|
|
58
|
+
|
|
59
|
+
#### DSP & Buyer Management
|
|
60
|
+
- Real API data for DSP and Buyer pages
|
|
61
|
+
- DSP list is read-only; Buyer CRUD operations with real API integration
|
|
62
|
+
- DSP and Buyer management added to side menu
|
|
63
|
+
|
|
64
|
+
#### UI/Layout
|
|
65
|
+
- Sticky sidebar navigation
|
|
66
|
+
- Theme selection in profile dropdown
|
|
67
|
+
- External links for inventory and measure pages in sidebar
|
|
68
|
+
- Custom toggle switch component for better visibility
|
|
69
|
+
|
|
70
|
+
### Deals List Page
|
|
71
|
+
- Search bar, bordered table card, Type (PD/PG/Traditional), Source (Influence/Activate/Planner), amber badges
|
|
72
|
+
|
|
73
|
+
### Sidebar & Header
|
|
74
|
+
- "DOOH Adserver" branding with blue "I" icon
|
|
75
|
+
|
|
76
|
+
### Line Item Creatives Page
|
|
77
|
+
- Breadcrumbs, 4 metric cards, player status bar, search/filter toolbar, table view
|
|
78
|
+
- "Assign Creative" opens full-width side Sheet popover (not page navigation)
|
|
79
|
+
|
|
80
|
+
### Creative Assignment Page
|
|
81
|
+
- Opens as full-width Sheet/popover overlay from Line Item Creatives page
|
|
82
|
+
- Left sidebar: numbered creative requirements with resolution/duration/type/inventory, drag-and-drop zones
|
|
83
|
+
- Right panel: Content Hub with search, filters, 4-column draggable card grid
|
|
84
|
+
- Sticky footer: Cancel / Save Assignment
|
|
85
|
+
|
|
86
|
+
### Line Item Form - Base Pricing
|
|
87
|
+
- Programmatic: `bidFloorBase` (original bid floor before custom fees)
|
|
88
|
+
- Direct: `pricing.cpmBase`, `pricing.estimatedCostBase` (original values before custom fees)
|
|
89
|
+
|
|
90
|
+
### Programmatic Deal Creation (PCM-Aligned)
|
|
91
|
+
- Cascading dependency: Deal Type → DSP → Buyer → Transaction Type → Currency
|
|
92
|
+
- No brand field for programmatic deals (brand only for DIRECT mode)
|
|
93
|
+
- Centralized DSP dropdown (not per-buyer rows); DSP disabled until Deal Type selected
|
|
94
|
+
- Buyer dropdown disabled until DSP selected; adds buyers as removable chips/badges
|
|
95
|
+
- Buyer constraints: single buyer for GUARANTEED/PREFERRED_DEAL, multiple for PRIVATE_AUCTION/EVERGREEN_PMP
|
|
96
|
+
- After buyer selection, DSP and Deal Type fields become locked
|
|
97
|
+
- Auction Type: HIDDEN except for PRIVATE_AUCTION (First Price / Second Price); auto-set to 3 for all others
|
|
98
|
+
- Hard Stop: only visible for GUARANTEED deal type
|
|
99
|
+
- Non-Billable: always visible as checkbox
|
|
100
|
+
- Impression Multiplier Type (MAD/CUSTOM): only visible when transactionType === AUDIENCE
|
|
101
|
+
- Seller section: name, phone, email fields with auto-populate from logged-in user
|
|
102
|
+
- Description textarea for optional notes
|
|
103
|
+
- Remove buyer resets dealType/DSP when last buyer removed
|
|
104
|
+
- Edit mode locks dealType (always), locks DSP when buyers exist
|
|
105
|
+
|
|
106
|
+
### Deal Page Buyer Management (Legacy)
|
|
107
|
+
- DSP dropdown loads from `getDspDropdownList()` API with flexible field mapping (id/value/code, name/label/description)
|
|
108
|
+
- Buyers load from `listDspBuyers()` API, filtered by both `dspId` and `name` query params
|
|
109
|
+
- Both `activeDspId` and `activeDspName` are tracked; fallback to raw value if DSP not found in options
|
|
110
|
+
- Edit mode maps DSP names to IDs and resolves `buyerId` by matching `seatId` or `buyerName`
|
|
111
|
+
|
|
112
|
+
### Line Item Form - Targeting Section (Prototype-aligned)
|
|
113
|
+
- Targeting section uses row-based design: flat rows with icon, label, count/status, checkmark
|
|
114
|
+
- Age Groups and Gender are separate expandable rows with inline checkbox grids
|
|
115
|
+
- POI Targeting opens a side drawer with POIs/Categories tabs, search, and checkboxes
|
|
116
|
+
- Venue Type opens a side drawer with search and checkboxes (recursive tree, API-driven)
|
|
117
|
+
- Both drawers have Cancel/Apply sticky footers and manage local state before persisting
|
|
118
|
+
- POI selections stored in `selectedPOIs` form field
|
|
119
|
+
|
|
120
|
+
### Line Item Detail Page
|
|
121
|
+
- Full-page DV360-style detail view at `/deals/:dealId/line-items/:lineItemId`
|
|
122
|
+
- Shows summary cards (Budget, Impressions, Revenue, Dates), overview, targeting, inventories, creatives
|
|
123
|
+
- Line item row click in deal page navigates to detail page instead of opening side sheet
|
|
124
|
+
|
|
125
|
+
### Deal Page - History Button
|
|
126
|
+
- Deal History moved from dropdown menu to icon-only button with tooltip next to Filter icon
|
|
127
|
+
|
|
128
|
+
### Navigation Flow
|
|
129
|
+
- Line Items → Click row → Line Item Detail page → Edit button → Line Item Form
|
|
130
|
+
- Line Items → Creatives list → Assign Creative → Creative Assignment page → Back/Cancel → Creatives list
|
|
131
|
+
|
|
132
|
+
## System Architecture
|
|
133
|
+
|
|
134
|
+
### Frontend Architecture
|
|
135
|
+
- **Framework**: React 18 with TypeScript, built using Vite.
|
|
136
|
+
- **Styling**: Tailwind CSS with custom design tokens, leveraging Radix UI primitives, MWDesign System (`@moving-walls/design-system`), and shadcn/ui patterns.
|
|
137
|
+
- **State Management**: TanStack React Query for server state and Redux Toolkit for geofencing map state.
|
|
138
|
+
- **Forms**: React Hook Form with Zod validation.
|
|
139
|
+
- **Maps**: Mapbox GL for interactive geofencing and location features.
|
|
140
|
+
- **Routing**: wouter for client-side routing.
|
|
141
|
+
- **Internationalization**: Tolgee for multi-language support (English, Japanese, Chinese, Arabic) with in-context editing in development.
|
|
142
|
+
|
|
143
|
+
### Backend Architecture
|
|
144
|
+
- The current deployment is frontend-only (static site via Vite).
|
|
145
|
+
- The frontend interacts with external API endpoints.
|
|
146
|
+
- Authentication is OAuth-based with SSO integration.
|
|
147
|
+
|
|
148
|
+
### Project Structure
|
|
149
|
+
- `client/src/`: React frontend application (components, pages, hooks, lib).
|
|
150
|
+
- `shared/`: Shared TypeScript types and schemas.
|
|
151
|
+
- `e2e/`: Playwright end-to-end tests.
|
|
152
|
+
- `docs/`: Documentation.
|
|
153
|
+
- `terraform/`: Infrastructure as Code (AWS).
|
|
154
|
+
- `.ci/`: GitLab CI/CD pipelines.
|
|
155
|
+
|
|
156
|
+
### Design System
|
|
157
|
+
- Utilizes the `@moving-walls/design-system` npm package, offering 50+ React components and 1000+ Lucide icons.
|
|
158
|
+
- Design tokens are managed via CSS custom properties.
|
|
159
|
+
|
|
160
|
+
### Feature Specifications
|
|
161
|
+
- **Campaign Management**: Supports DIRECT and PROGRAMMATIC deal modes, with mode-aware wizards for deal creation and line item configuration.
|
|
162
|
+
- **DSP/Buyer Management**: Read-only DSP list and CRUD operations for DSP buyers with real API integration.
|
|
163
|
+
- **Line Item Form**: Single-page form with collapsible accordion sections, a two-column layout (form + sidebar for insights/tips/forecast), and dynamic input types (e.g., pill buttons for ad duration). Includes base pricing fields: `bidFloorBase` (programmatic) and `pricing.cpmBase`/`pricing.estimatedCostBase` (direct) for storing original values before custom fees.
|
|
164
|
+
- **Creative Management**: Split-view assignment page with drag-and-drop from Content Hub, grouped creative requirements, and status tracking.
|
|
165
|
+
- **Content Hub**: Unified page (`content-hub.tsx`) with grid/list views, folder cards, creative preview sheet (tags, status actions, download, transcode, delete), filter drawer, and pagination. All API integrations preserved (useFolders, useCreatives, useDeleteCreative, useApproveCreative, useRejectCreative, useUpdateCreative, useTranscodeCreative, useCreateFolder). The `/creatives` route delegates to this page.
|
|
166
|
+
- **Reporting & Analytics**: Dashboard with key metrics, impression delivery progress, and various reports for performance insights.
|
|
167
|
+
- **New Pages**: Integrates pages for Dashboard, Reports, Signals, Proof of Play, and Integrations with SSP/DSP partners.
|
|
168
|
+
- **Configuration Pages**: Settings (11 config sections), Tags (color-coded tag management), and Custom POIs (geolocation management with upload/create). All UI-only with mock data.
|
|
169
|
+
- **Profile Dropdown**: Settings navigates to in-app /settings page instead of external URL.
|
|
170
|
+
|
|
171
|
+
## External Dependencies
|
|
172
|
+
|
|
173
|
+
### Maps & Geolocation
|
|
174
|
+
- **Mapbox GL**: Core mapping library.
|
|
175
|
+
- **Mapbox GL Draw**: For creating and editing geofences.
|
|
176
|
+
- **Mapbox GL Geocoder**: For location search functionality.
|
|
177
|
+
|
|
178
|
+
### UI Component Libraries
|
|
179
|
+
- **Radix UI**: Provides accessible, unstyled UI primitives.
|
|
180
|
+
- **cmdk**: For command palette interface.
|
|
181
|
+
- **embla-carousel-react**: For carousel components.
|
|
182
|
+
- **date-fns**: For date manipulation and formatting.
|
|
183
|
+
|
|
184
|
+
### Internationalization
|
|
185
|
+
- **@tolgee/react**: For translation management and in-context editing.
|
|
186
|
+
|
|
187
|
+
### Testing
|
|
188
|
+
- **Vitest**: For unit testing with `@testing-library/react` and `jsdom`.
|
|
189
|
+
- **Playwright**: For end-to-end testing.
|
|
190
|
+
|
|
191
|
+
### Infrastructure (Terraform)
|
|
192
|
+
- **AWS Services**: CloudFront, S3, WAF, Route53, ACM for deployment and security.
|
|
193
|
+
|
|
194
|
+
### Environment Configuration
|
|
195
|
+
- Requires Mapbox API tokens.
|
|
196
|
+
- Requires SSO configuration for authentication.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/screenshot.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { chromium } from 'playwright';
|
|
2
|
+
|
|
3
|
+
const browser = await chromium.launch();
|
|
4
|
+
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
|
|
5
|
+
|
|
6
|
+
// Go to login page
|
|
7
|
+
await page.goto('http://localhost:5000/login', { waitUntil: 'networkidle', timeout: 30000 });
|
|
8
|
+
await page.waitForTimeout(1000);
|
|
9
|
+
|
|
10
|
+
// Fill and submit login
|
|
11
|
+
await page.fill('input[type="email"], input[id*="email"], input[name*="email"]', 'jeki@jeki.com');
|
|
12
|
+
await page.fill('input[type="password"], input[id*="password"], input[name*="password"]', 'Jeki@123');
|
|
13
|
+
await page.click('button[type="submit"]');
|
|
14
|
+
|
|
15
|
+
// Quickly capture the loading state
|
|
16
|
+
await page.waitForTimeout(500);
|
|
17
|
+
await page.screenshot({ path: 'screenshot-auth-loader.png' });
|
|
18
|
+
console.log('Auth loader screenshot taken');
|
|
19
|
+
|
|
20
|
+
await page.waitForTimeout(3000);
|
|
21
|
+
await page.screenshot({ path: 'screenshot-auth-loader-2.png' });
|
|
22
|
+
console.log('Auth loader 2nd screenshot taken');
|
|
23
|
+
|
|
24
|
+
await browser.close();
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Deployment script for MW-Influence-Adserver-FE
|
|
3
|
+
# Uses existing S3 bucket: s3://moving-audience-unified/influence-adserver-stg/
|
|
4
|
+
# CloudFront Distribution: MW-Influence-Adserver-FE (based on Inventory-STG reference)
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "======================================"
|
|
9
|
+
echo "MW Influence AdServer - STG Deployment"
|
|
10
|
+
echo "======================================"
|
|
11
|
+
|
|
12
|
+
# Configuration
|
|
13
|
+
S3_BUCKET="moving-audience-unified"
|
|
14
|
+
S3_PREFIX="influence-adserver-stg"
|
|
15
|
+
CLOUDFRONT_DISTRIBUTION_NAME="MW-Influence-Adserver-FE"
|
|
16
|
+
AWS_REGION="${AWS_REGION:-us-east-1}"
|
|
17
|
+
|
|
18
|
+
# Colors for output
|
|
19
|
+
RED='\033[0;31m'
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
NC='\033[0m' # No Color
|
|
23
|
+
|
|
24
|
+
# Function to print colored output
|
|
25
|
+
print_info() {
|
|
26
|
+
echo -e "${GREEN}[INFO]${NC} $1"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
print_warning() {
|
|
30
|
+
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
print_error() {
|
|
34
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Check if AWS CLI is installed
|
|
38
|
+
if ! command -v aws &> /dev/null; then
|
|
39
|
+
print_error "AWS CLI is not installed. Please install it first."
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
print_info "AWS CLI version: $(aws --version)"
|
|
44
|
+
|
|
45
|
+
# Check AWS credentials
|
|
46
|
+
print_info "Checking AWS credentials..."
|
|
47
|
+
if ! aws sts get-caller-identity &> /dev/null; then
|
|
48
|
+
print_error "AWS credentials not configured. Run 'aws configure' first."
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
print_info "AWS Account: $(aws sts get-caller-identity --query Account --output text)"
|
|
53
|
+
|
|
54
|
+
# Step 1: Build MWDesign
|
|
55
|
+
print_info "Building MWDesign component library..."
|
|
56
|
+
cd MWDesign
|
|
57
|
+
if [ ! -d "node_modules" ]; then
|
|
58
|
+
print_info "Installing MWDesign dependencies..."
|
|
59
|
+
npm ci --production=false
|
|
60
|
+
fi
|
|
61
|
+
npm run build:package
|
|
62
|
+
print_info "✅ MWDesign build complete"
|
|
63
|
+
cd ..
|
|
64
|
+
|
|
65
|
+
# Step 2: Build AdServer Frontend
|
|
66
|
+
print_info "Building AdServer frontend..."
|
|
67
|
+
cd adserver
|
|
68
|
+
if [ ! -d "node_modules" ]; then
|
|
69
|
+
print_info "Installing adserver dependencies..."
|
|
70
|
+
npm ci --production=false
|
|
71
|
+
fi
|
|
72
|
+
npm run build:frontend
|
|
73
|
+
print_info "✅ AdServer frontend build complete"
|
|
74
|
+
|
|
75
|
+
# Step 3: Verify build output
|
|
76
|
+
if [ ! -d "dist/client" ]; then
|
|
77
|
+
print_error "Build failed - dist/client directory not found"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
print_info "Build output size: $(du -sh dist/client | cut -f1)"
|
|
82
|
+
|
|
83
|
+
# Step 4: Sync to S3
|
|
84
|
+
print_info "Deploying to S3: s3://${S3_BUCKET}/${S3_PREFIX}/"
|
|
85
|
+
|
|
86
|
+
# Sync static assets (JS, CSS, images) with long cache
|
|
87
|
+
print_info "Uploading static assets with cache-control..."
|
|
88
|
+
aws s3 sync dist/client s3://${S3_BUCKET}/${S3_PREFIX}/ \
|
|
89
|
+
--delete \
|
|
90
|
+
--cache-control "public, max-age=31536000, immutable" \
|
|
91
|
+
--exclude "*.html" \
|
|
92
|
+
--exclude "*.json" \
|
|
93
|
+
--exclude "service-worker.js" \
|
|
94
|
+
--region ${AWS_REGION}
|
|
95
|
+
|
|
96
|
+
# Sync HTML and JSON files with no cache
|
|
97
|
+
print_info "Uploading HTML and JSON files without cache..."
|
|
98
|
+
aws s3 sync dist/client s3://${S3_BUCKET}/${S3_PREFIX}/ \
|
|
99
|
+
--cache-control "public, max-age=0, must-revalidate" \
|
|
100
|
+
--exclude "*" \
|
|
101
|
+
--include "*.html" \
|
|
102
|
+
--include "*.json" \
|
|
103
|
+
--include "service-worker.js" \
|
|
104
|
+
--region ${AWS_REGION}
|
|
105
|
+
|
|
106
|
+
print_info "✅ S3 sync complete"
|
|
107
|
+
|
|
108
|
+
# Step 5: Get CloudFront Distribution ID
|
|
109
|
+
print_info "Finding CloudFront distribution ID for ${CLOUDFRONT_DISTRIBUTION_NAME}..."
|
|
110
|
+
DISTRIBUTION_ID=$(aws cloudfront list-distributions \
|
|
111
|
+
--query "DistributionList.Items[?Comment=='${CLOUDFRONT_DISTRIBUTION_NAME}'].Id | [0]" \
|
|
112
|
+
--output text \
|
|
113
|
+
--region us-east-1)
|
|
114
|
+
|
|
115
|
+
if [ "$DISTRIBUTION_ID" == "None" ] || [ -z "$DISTRIBUTION_ID" ]; then
|
|
116
|
+
print_warning "CloudFront distribution '${CLOUDFRONT_DISTRIBUTION_NAME}' not found by comment."
|
|
117
|
+
print_info "Searching by origin domain name..."
|
|
118
|
+
|
|
119
|
+
DISTRIBUTION_ID=$(aws cloudfront list-distributions \
|
|
120
|
+
--query "DistributionList.Items[?Origins.Items[?DomainName=='${S3_BUCKET}.s3.amazonaws.com']].Id | [0]" \
|
|
121
|
+
--output text \
|
|
122
|
+
--region us-east-1)
|
|
123
|
+
|
|
124
|
+
if [ "$DISTRIBUTION_ID" == "None" ] || [ -z "$DISTRIBUTION_ID" ]; then
|
|
125
|
+
print_error "CloudFront distribution not found. Please set CLOUDFRONT_DISTRIBUTION_ID environment variable."
|
|
126
|
+
print_info "You can find it by running: aws cloudfront list-distributions --query 'DistributionList.Items[*].[Id,Comment]'"
|
|
127
|
+
|
|
128
|
+
# If CLOUDFRONT_DISTRIBUTION_ID is set, use it
|
|
129
|
+
if [ ! -z "$CLOUDFRONT_DISTRIBUTION_ID" ]; then
|
|
130
|
+
DISTRIBUTION_ID=$CLOUDFRONT_DISTRIBUTION_ID
|
|
131
|
+
print_info "Using distribution ID from environment: $DISTRIBUTION_ID"
|
|
132
|
+
else
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
print_info "CloudFront Distribution ID: $DISTRIBUTION_ID"
|
|
139
|
+
|
|
140
|
+
# Step 6: Invalidate CloudFront Cache
|
|
141
|
+
print_info "Creating CloudFront invalidation..."
|
|
142
|
+
INVALIDATION_ID=$(aws cloudfront create-invalidation \
|
|
143
|
+
--distribution-id ${DISTRIBUTION_ID} \
|
|
144
|
+
--paths "/*" \
|
|
145
|
+
--query 'Invalidation.Id' \
|
|
146
|
+
--output text \
|
|
147
|
+
--region us-east-1)
|
|
148
|
+
|
|
149
|
+
print_info "Invalidation ID: $INVALIDATION_ID"
|
|
150
|
+
print_info "Waiting for invalidation to complete (this may take a few minutes)..."
|
|
151
|
+
|
|
152
|
+
# Wait for invalidation to complete
|
|
153
|
+
aws cloudfront wait invalidation-completed \
|
|
154
|
+
--distribution-id ${DISTRIBUTION_ID} \
|
|
155
|
+
--id ${INVALIDATION_ID} \
|
|
156
|
+
--region us-east-1 || print_warning "Invalidation is in progress..."
|
|
157
|
+
|
|
158
|
+
print_info "✅ CloudFront cache invalidated"
|
|
159
|
+
|
|
160
|
+
# Step 7: Get CloudFront URL
|
|
161
|
+
CLOUDFRONT_URL=$(aws cloudfront get-distribution \
|
|
162
|
+
--id ${DISTRIBUTION_ID} \
|
|
163
|
+
--query 'Distribution.DomainName' \
|
|
164
|
+
--output text \
|
|
165
|
+
--region us-east-1)
|
|
166
|
+
|
|
167
|
+
# Summary
|
|
168
|
+
echo ""
|
|
169
|
+
echo "======================================"
|
|
170
|
+
echo "Deployment Summary"
|
|
171
|
+
echo "======================================"
|
|
172
|
+
print_info "Environment: STAGING"
|
|
173
|
+
print_info "S3 Bucket: s3://${S3_BUCKET}/${S3_PREFIX}/"
|
|
174
|
+
print_info "CloudFront Distribution: ${CLOUDFRONT_DISTRIBUTION_NAME}"
|
|
175
|
+
print_info "Distribution ID: ${DISTRIBUTION_ID}"
|
|
176
|
+
print_info "CloudFront URL: https://${CLOUDFRONT_URL}"
|
|
177
|
+
print_info "Invalidation ID: ${INVALIDATION_ID}"
|
|
178
|
+
echo ""
|
|
179
|
+
print_info "✅ Deployment completed successfully!"
|
|
180
|
+
echo ""
|
|
181
|
+
print_info "Test your deployment:"
|
|
182
|
+
print_info " curl -I https://${CLOUDFRONT_URL}"
|
|
183
|
+
echo "======================================"
|
|
184
|
+
|
|
185
|
+
cd ..
|