diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 85f6d174..2db19740 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -418,11 +418,32 @@ jobs: scp .env.deploy root@alpha.mintel.me:$SITE_DIR/$ENV_FILE scp docker-compose.yml root@alpha.mintel.me:$SITE_DIR/docker-compose.yml + APP_CONTAINER="${{ needs.prepare.outputs.project_name }}-klz-app-1" + DB_CONTAINER="${{ needs.prepare.outputs.project_name }}-klz-db-1" + + # Branch Seeding Logic (Production -> Branch) + if [[ "$TARGET" == "branch" ]]; then + echo "🌱 Seeding Branch Environment from Production Database..." + ssh root@alpha.mintel.me "cd $SITE_DIR && docker compose -p '${{ needs.prepare.outputs.project_name }}' --env-file $ENV_FILE pull && docker compose -p '${{ needs.prepare.outputs.project_name }}' --env-file $ENV_FILE up -d klz-db" + + # Wait for DB to be healthy + echo "Waiting for branch database to be ready..." + sleep 10 + ssh root@alpha.mintel.me "docker exec $DB_CONTAINER pg_isready -U payload" || sleep 10 + + # Copy Production Payload DB to Branch Payload DB & ensure media is copied + echo "📦 Syncing Production DB into Branch DB..." + ssh root@alpha.mintel.me " + docker exec klz-cablescom-klz-db-1 pg_dump -U payload -d payload --clean --if-exists | docker exec -i $DB_CONTAINER psql -U payload -d payload --quiet + rsync -a --delete /var/lib/docker/volumes/klz-cablescom_klz_media_data/_data/ /var/lib/docker/volumes/${{ needs.prepare.outputs.project_name }}_klz_media_data/_data/ + " + echo "✅ Branch database and media synced successfully." + fi + # Execute remote commands — alpha is pre-logged into registry.infra.mintel.me ssh root@alpha.mintel.me "cd $SITE_DIR && docker compose -p '${{ needs.prepare.outputs.project_name }}' --env-file $ENV_FILE pull && docker compose -p '${{ needs.prepare.outputs.project_name }}' --env-file $ENV_FILE up -d --remove-orphans" # Restart app to pick up clean migration state - APP_CONTAINER="${{ needs.prepare.outputs.project_name }}-klz-app-1" ssh root@alpha.mintel.me "docker restart $APP_CONTAINER" ssh root@alpha.mintel.me "docker system prune -f --filter 'until=24h'" diff --git a/components/BrochureModal.tsx b/components/BrochureModal.tsx index c71dd604..f16c01b8 100644 --- a/components/BrochureModal.tsx +++ b/components/BrochureModal.tsx @@ -57,10 +57,12 @@ export default function BrochureModal({ isOpen, onClose }: BrochureModalProps) { document.addEventListener('keydown', handleKeyDown); // Strict overflow lock on mobile as well + document.documentElement.style.setProperty('overflow', 'hidden', 'important'); document.body.style.setProperty('overflow', 'hidden', 'important'); return () => { document.removeEventListener('keydown', handleKeyDown); + document.documentElement.style.overflow = ''; document.body.style.overflow = ''; }; }, [isOpen, onClose]); diff --git a/components/Header.tsx b/components/Header.tsx index e3d3688b..e151e358 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -36,6 +36,7 @@ export default function Header() { // Prevent scroll when mobile menu is open and handle focus trap useEffect(() => { if (isMobileMenuOpen) { + document.documentElement.style.overflow = 'hidden'; document.body.style.overflow = 'hidden'; // Focus trap logic const focusableElements = mobileMenuRef.current?.querySelectorAll( @@ -80,7 +81,8 @@ export default function Header() { }; } } else { - document.body.style.overflow = 'unset'; + document.documentElement.style.overflow = ''; + document.body.style.overflow = ''; } }, [isMobileMenuOpen]); diff --git a/components/Lightbox.tsx b/components/Lightbox.tsx index a6990372..5361c210 100644 --- a/components/Lightbox.tsx +++ b/components/Lightbox.tsx @@ -125,13 +125,17 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh }; // Lock scroll - const originalStyle = window.getComputedStyle(document.body).overflow; - document.body.style.overflow = 'hidden'; + const originalBodyStyle = window.getComputedStyle(document.body).overflow; + const originalHtmlStyle = window.getComputedStyle(document.documentElement).overflow; + + document.documentElement.style.setProperty('overflow', 'hidden', 'important'); + document.body.style.setProperty('overflow', 'hidden', 'important'); window.addEventListener('keydown', handleKeyDown); return () => { - document.body.style.overflow = originalStyle; + document.documentElement.style.overflow = originalHtmlStyle; + document.body.style.overflow = originalBodyStyle; window.removeEventListener('keydown', handleKeyDown); }; }, [isOpen, prevImage, nextImage, handleClose]); diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c7..c4b7818f 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/scripts/create-agent-admin.ts b/scripts/create-agent-admin.ts new file mode 100644 index 00000000..d524d6b1 --- /dev/null +++ b/scripts/create-agent-admin.ts @@ -0,0 +1,41 @@ +import { getPayload } from 'payload'; +import config from '../payload.config'; + +async function run() { + try { + const payload = await getPayload({ config: await config }); + const user = await payload.create({ + collection: 'users', + data: { + email: 'agent@mintel.me', + password: 'agentpassword123', + }, + }); + console.log('SUCCESS: Created AI Agent admin user', user.id); + } catch (e) { + if ( + e.message?.includes('duplicate key') || + e.code === '11000' || + String(e).includes('already exists') + ) { + console.log('User already exists, attempting to update password...', e.message); + const payload = await getPayload({ config: await config }); + const users = await payload.find({ + collection: 'users', + where: { email: { equals: 'agent@mintel.me' } }, + }); + if (users.docs.length > 0) { + await payload.update({ + collection: 'users', + id: users.docs[0].id, + data: { password: 'agentpassword123' }, + }); + console.log('SUCCESS: Updated existing AI Agent admin user password'); + } + } else { + console.error('ERROR creating user:', e); + } + } + process.exit(0); +} +run();