Compare commits
1 Commits
main
...
unfinished
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02c7f4e2aa |
63
.dockerignore
Normal file
@@ -0,0 +1,63 @@
|
||||
# Git files
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# Docker files
|
||||
Dockerfile*
|
||||
docker-compose*.yml
|
||||
.dockerignore
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
DEPLOYMENT_GUIDE.md
|
||||
*.md
|
||||
|
||||
# Development files
|
||||
.env.example
|
||||
.env.local
|
||||
.env.testing
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Node modules and build files
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Laravel specific
|
||||
/vendor
|
||||
/storage/logs/*
|
||||
!/storage/logs/.gitkeep
|
||||
/storage/framework/cache/*
|
||||
!/storage/framework/cache/.gitkeep
|
||||
/storage/framework/sessions/*
|
||||
!/storage/framework/sessions/.gitkeep
|
||||
/storage/framework/views/*
|
||||
!/storage/framework/views/.gitkeep
|
||||
/bootstrap/cache/*
|
||||
!/bootstrap/cache/.gitkeep
|
||||
|
||||
# Testing
|
||||
/tests
|
||||
phpunit.xml
|
||||
phpspec.yml
|
||||
|
||||
# Build tools
|
||||
gulpfile.js
|
||||
package.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Scripts
|
||||
start-local.sh
|
||||
rebuild.sh
|
||||
36
.env.local
@@ -1,36 +0,0 @@
|
||||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_KEY=base64:YOUR_APP_KEY_HERE
|
||||
|
||||
DB_HOST=db
|
||||
DB_DATABASE=merchbay
|
||||
DB_USERNAME=merchbay
|
||||
DB_PASSWORD=secret
|
||||
DB_PORT=3306
|
||||
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
|
||||
# Local mail (logs to storage/logs/laravel.log)
|
||||
MAIL_DRIVER=log
|
||||
MAIL_HOST=localhost
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
# Local URLs
|
||||
APP_URL=http://localhost:8080
|
||||
PROD_PRIVATE=http://localhost:8080
|
||||
IMAGES_URL=http://localhost:8080
|
||||
UPLOAD_URL=http://localhost:8080/uploads/
|
||||
|
||||
# Test Captcha (for local dev)
|
||||
CAPTCHA_SITE_KEY=test_key
|
||||
CAPTCHA_SECRET_KEY=test_secret
|
||||
|
||||
# Analytics (optional for local)
|
||||
ANALYTICS_SITE_ID=
|
||||
ANALYTICS_CLIENT_ID=
|
||||
ANALYTICS_SERVICE_EMAIL=
|
||||
@@ -1,57 +0,0 @@
|
||||
name: Build and Push Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Docker image tag (e.g., v1.0.0, latest)'
|
||||
required: false
|
||||
default: 'latest'
|
||||
push_to_registry:
|
||||
description: 'Push to registry?'
|
||||
required: false
|
||||
default: 'true'
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ secrets.DOCKER_REGISTRY_URL }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_REGISTRY_URL }}/merchbay
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY_URL }}/merchbay:buildcache
|
||||
cache-to: type=registry,ref=${{ secrets.DOCKER_REGISTRY_URL }}/merchbay:buildcache,mode=max
|
||||
@@ -1,161 +0,0 @@
|
||||
name: Deploy Development
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
|
||||
steps:
|
||||
# 1️⃣ Checkout code
|
||||
- name: Checkout code
|
||||
shell: sh
|
||||
run: |
|
||||
git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git /workspace/repo
|
||||
cd /workspace/repo
|
||||
git checkout $GITHUB_REF_NAME
|
||||
|
||||
# 2️⃣ Build image
|
||||
- name: Build Docker image
|
||||
shell: sh
|
||||
run: |
|
||||
cd /workspace/repo
|
||||
docker build -t merchbay:dev .
|
||||
docker save merchbay:dev | gzip > merchbay_dev.tar.gz
|
||||
|
||||
# 3️⃣ Setup SSH
|
||||
- name: Setup SSH
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||
|
||||
# 4️⃣ Upload artifacts
|
||||
- name: Upload image and compose
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
run: |
|
||||
scp -i ~/.ssh/id_ed25519 \
|
||||
/workspace/repo/merchbay_dev.tar.gz \
|
||||
/workspace/repo/docker-compose.dev.yml \
|
||||
${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/
|
||||
|
||||
# 5️⃣ Deploy on server
|
||||
- name: Deploy on server
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
|
||||
run: |
|
||||
ssh -i ~/.ssh/id_ed25519 $DEPLOY_USER@$DEPLOY_HOST << 'EOF'
|
||||
set -e
|
||||
|
||||
DEPLOY_DIR="/var/www/apps/merchbay_dev"
|
||||
mkdir -p "$DEPLOY_DIR"
|
||||
|
||||
echo "📦 Loading image"
|
||||
docker load < /tmp/merchbay_dev.tar.gz
|
||||
|
||||
echo "🧹 Removing old merchbay images"
|
||||
docker images | grep merchbay | grep -v "$(docker images merchbay:dev -q)" | awk '{print $3}' | xargs -r docker rmi -f || true
|
||||
|
||||
echo "📄 Updating compose file"
|
||||
cp /tmp/docker-compose.dev.yml "$DEPLOY_DIR/docker-compose.yml"
|
||||
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
echo "🔍 Checking .env file"
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ .env file not found at $DEPLOY_DIR/.env"
|
||||
echo "Please create it first with required variables:"
|
||||
echo " - DB_*, PROD_PRIVATE, IMAGES_URL, UPLOAD_URL"
|
||||
echo " - MAIL_*, CAPTCHA_*, ANALYTICS_*"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔧 Fixing .env permissions"
|
||||
sudo chown $USER:$USER .env
|
||||
sudo chmod 600 .env
|
||||
|
||||
echo "🌐 Ensure networks"
|
||||
docker network inspect traefik-public >/dev/null 2>&1 || \
|
||||
docker network create traefik-public
|
||||
docker network inspect crew-app-net >/dev/null 2>&1 || \
|
||||
docker network create crew-app-net
|
||||
|
||||
echo "🚀 Starting containers (env vars from .env file)"
|
||||
docker compose up -d
|
||||
|
||||
echo "⏳ Waiting for app container"
|
||||
sleep 15
|
||||
|
||||
if docker ps --format '{{.Names}}' | grep -q merchbay_app; then
|
||||
echo "🧹 Clearing and rebuilding config cache"
|
||||
docker compose exec -T app php artisan config:clear
|
||||
docker compose exec -T app php artisan config:cache
|
||||
else
|
||||
echo "❌ App container not running"
|
||||
docker compose logs
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🧹 Cleanup"
|
||||
rm -f /tmp/merchbay_dev.tar.gz /tmp/docker-compose.dev.yml
|
||||
|
||||
echo "🧹 Aggressive Docker cleanup to reclaim space"
|
||||
docker image prune -af --filter "until=24h" || true
|
||||
docker container prune -f || true
|
||||
docker volume prune -f || true
|
||||
docker builder prune -af --filter "until=48h" || true
|
||||
echo "📊 Docker space usage:"
|
||||
docker system df
|
||||
|
||||
echo "✅ Deployment completed"
|
||||
EOF
|
||||
|
||||
|
||||
# 6️⃣ Health check
|
||||
- name: Health check
|
||||
shell: sh
|
||||
run: |
|
||||
echo "⏳ Waiting for app to be ready..."
|
||||
sleep 20
|
||||
|
||||
echo "🔍 Testing health check (ignoring SSL cert for now)..."
|
||||
HTTP_CODE=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 30 https://dev.merchbay.app || echo "000")
|
||||
|
||||
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ] || [ "$HTTP_CODE" = "301" ]; then
|
||||
echo "✅ Health check passed! (HTTP $HTTP_CODE)"
|
||||
echo "⚠️ Note: Using -k to ignore SSL cert. Check Traefik logs if cert not ready."
|
||||
else
|
||||
echo "❌ Health check failed! (HTTP $HTTP_CODE)"
|
||||
echo ""
|
||||
echo "💡 Troubleshooting:"
|
||||
echo " 1. Check if container is running:"
|
||||
echo " docker ps | grep merchbay_app"
|
||||
echo ""
|
||||
echo " 2. Check app logs:"
|
||||
echo " docker logs merchbay_app"
|
||||
echo ""
|
||||
echo " 3. Check Traefik logs:"
|
||||
echo " docker logs traefik"
|
||||
echo ""
|
||||
echo " 4. Test manually:"
|
||||
echo " curl -Ik https://dev.merchbay.app"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,181 +0,0 @@
|
||||
name: Deploy Production (merchbay.com)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
|
||||
steps:
|
||||
# 1️⃣ Checkout code
|
||||
- name: Checkout code
|
||||
shell: sh
|
||||
run: |
|
||||
git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git /workspace/repo
|
||||
cd /workspace/repo
|
||||
git checkout $GITHUB_REF_NAME
|
||||
|
||||
# 2️⃣ Build image
|
||||
- name: Build Docker image
|
||||
shell: sh
|
||||
run: |
|
||||
cd /workspace/repo
|
||||
docker build -t merchbay:latest .
|
||||
docker save merchbay:latest | gzip > merchbay.tar.gz
|
||||
|
||||
# 3️⃣ Setup SSH
|
||||
- name: Setup SSH
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||
|
||||
# 4️⃣ Upload artifacts
|
||||
- name: Upload image and compose
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
run: |
|
||||
scp -i ~/.ssh/id_ed25519 \
|
||||
/workspace/repo/merchbay.tar.gz \
|
||||
/workspace/repo/docker-compose.prod.yml \
|
||||
${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/
|
||||
|
||||
# 5️⃣ Deploy on server
|
||||
- name: Deploy on server
|
||||
shell: sh
|
||||
env:
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
|
||||
run: |
|
||||
ssh -i ~/.ssh/id_ed25519 $DEPLOY_USER@$DEPLOY_HOST << 'EOF'
|
||||
set -e
|
||||
|
||||
DEPLOY_DIR="/var/www/apps/merchbay"
|
||||
sudo mkdir -p "$DEPLOY_DIR"
|
||||
sudo chown $USER:$USER "$DEPLOY_DIR"
|
||||
|
||||
echo "<22> Stopping dev environment"
|
||||
DEV_DIR="/var/www/apps/merchbay_dev"
|
||||
if [ -d "$DEV_DIR" ]; then
|
||||
cd "$DEV_DIR"
|
||||
docker compose down || true
|
||||
cd -
|
||||
echo "✅ Dev environment stopped"
|
||||
echo "📋 Copying .env from dev to production"
|
||||
if [ -f "$DEV_DIR/.env" ]; then
|
||||
cp "$DEV_DIR/.env" "$DEPLOY_DIR/.env"
|
||||
echo "✅ .env file copied from dev to production"
|
||||
else
|
||||
echo "⚠️ No .env file found in dev directory"
|
||||
fi else
|
||||
echo "ℹ️ No dev environment found"
|
||||
fi
|
||||
|
||||
echo "📦 Loading image"
|
||||
docker load < /tmp/merchbay.tar.gz
|
||||
|
||||
echo "🧹 Removing dev images and old merchbay images"
|
||||
docker images | grep "merchbay:dev" | awk '{print $3}' | xargs -r docker rmi -f || true
|
||||
docker images | grep merchbay | grep -v "$(docker images merchbay:latest -q)" | awk '{print $3}' | xargs -r docker rmi -f || true
|
||||
|
||||
echo "📄 Updating compose file"
|
||||
cp /tmp/docker-compose.prod.yml "$DEPLOY_DIR/docker-compose.yml"
|
||||
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
echo "🔍 Checking .env file"
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ .env file not found at $DEPLOY_DIR/.env"
|
||||
echo "Please create it first with required variables:"
|
||||
echo " - DB_*, PROD_PRIVATE, IMAGES_URL, UPLOAD_URL"
|
||||
echo " - MAIL_*, CAPTCHA_*, ANALYTICS_*"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔧 Fixing .env permissions"
|
||||
sudo chown $USER:$USER .env
|
||||
sudo chmod 600 .env
|
||||
|
||||
echo "🌐 Ensure networks"
|
||||
docker network inspect traefik-public >/dev/null 2>&1 || \
|
||||
docker network create traefik-public
|
||||
docker network inspect crew-app-net >/dev/null 2>&1 || \
|
||||
docker network create crew-app-net
|
||||
|
||||
echo "🚀 Starting containers (env vars from .env file)"
|
||||
docker compose up -d
|
||||
|
||||
echo "⏳ Waiting for app container"
|
||||
sleep 15
|
||||
|
||||
if docker ps --format '{{.Names}}' | grep -q merchbay_app; then
|
||||
echo "🧹 Clearing and rebuilding config cache"
|
||||
docker compose exec -T app php artisan config:clear
|
||||
docker compose exec -T app php artisan config:cache
|
||||
else
|
||||
echo "❌ App container not running"
|
||||
docker compose logs
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🧹 Cleanup"
|
||||
rm -f /tmp/merchbay.tar.gz /tmp/docker-compose.prod.yml
|
||||
|
||||
echo "🧹 Aggressive Docker cleanup to reclaim space"
|
||||
docker image prune -af --filter "until=24h" || true
|
||||
docker container prune -f || true
|
||||
docker volume prune -f || true
|
||||
docker builder prune -af --filter "until=48h" || true
|
||||
echo "📊 Docker space usage:"
|
||||
docker system df
|
||||
|
||||
echo "✅ Production deployment completed!"
|
||||
echo "🌐 Application available at: https://merchbay.com"
|
||||
EOF
|
||||
|
||||
# 6️⃣ Health check
|
||||
- name: Health check
|
||||
shell: sh
|
||||
run: |
|
||||
echo "⏳ Waiting for app to be ready..."
|
||||
sleep 20
|
||||
|
||||
echo "🔍 Testing health check..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 https://merchbay.com || echo "000")
|
||||
|
||||
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ] || [ "$HTTP_CODE" = "301" ]; then
|
||||
echo "✅ Health check passed! (HTTP $HTTP_CODE)"
|
||||
echo "🎉 Production deployment successful!"
|
||||
else
|
||||
echo "❌ Health check failed! (HTTP $HTTP_CODE)"
|
||||
echo ""
|
||||
echo "💡 Troubleshooting:"
|
||||
echo " 1. Check if container is running:"
|
||||
echo " docker ps | grep merchbay_app"
|
||||
echo ""
|
||||
echo " 2. Check app logs:"
|
||||
echo " docker logs merchbay_app"
|
||||
echo ""
|
||||
echo " 3. Check Traefik logs:"
|
||||
echo " docker logs traefik"
|
||||
echo ""
|
||||
echo " 4. Test manually:"
|
||||
echo " curl -Ik https://merchbay.com"
|
||||
exit 1
|
||||
fi
|
||||
229
DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Google Cloud Run Deployment Guide for Merchbay Laravel Application
|
||||
|
||||
This guide will help you deploy your Laravel 5 application to Google Cloud Run using the provided `cloudbuild.yaml` configuration.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Google Cloud Project**: Ensure you have a Google Cloud Project with billing enabled
|
||||
2. **APIs Enabled**: Enable the following APIs:
|
||||
- Cloud Build API
|
||||
- Cloud Run API
|
||||
- Container Registry API (or Artifact Registry API)
|
||||
- Cloud SQL API (if using Cloud SQL)
|
||||
- Secret Manager API (recommended for secrets)
|
||||
|
||||
3. **gcloud CLI**: Install and configure the Google Cloud CLI
|
||||
|
||||
## Pre-deployment Setup
|
||||
|
||||
### 1. Create Cloud SQL Instance (Recommended)
|
||||
|
||||
```bash
|
||||
# Create MySQL instance
|
||||
gcloud sql instances create merchbay-db \
|
||||
--database-version=MYSQL_8_0 \
|
||||
--tier=db-f1-micro \
|
||||
--region=us-central1
|
||||
|
||||
# Create database
|
||||
gcloud sql databases create merchbay --instance=merchbay-db
|
||||
|
||||
# Create user
|
||||
gcloud sql users create laravel_user \
|
||||
--instance=merchbay-db \
|
||||
--password=YOUR_SECURE_PASSWORD
|
||||
```
|
||||
|
||||
### 2. Store Secrets in Secret Manager
|
||||
|
||||
```bash
|
||||
# Application key (generate a new one)
|
||||
echo "base64:$(openssl rand -base64 32)" | gcloud secrets create APP_KEY --data-file=-
|
||||
|
||||
# Database password
|
||||
echo "YOUR_DB_PASSWORD" | gcloud secrets create DB_PASSWORD --data-file=-
|
||||
|
||||
# PayPal secrets
|
||||
echo "YOUR_PAYPAL_LIVE_SECRET" | gcloud secrets create PAYPAL_LIVE_SECRET --data-file=-
|
||||
echo "YOUR_PAYPAL_SANDBOX_SECRET" | gcloud secrets create PAYPAL_SANDBOX_SECRET --data-file=-
|
||||
|
||||
# Mail password
|
||||
echo "YOUR_MAIL_PASSWORD" | gcloud secrets create MAIL_PASSWORD --data-file=-
|
||||
```
|
||||
|
||||
### 3. Update cloudbuild.yaml Variables
|
||||
|
||||
Update the substitution variables in `cloudbuild.yaml`:
|
||||
|
||||
```yaml
|
||||
substitutions:
|
||||
_SERVICE_NAME: 'merchbay-laravel'
|
||||
_REGION: 'us-central1' # Change to your preferred region
|
||||
_CLOUDSQL_INSTANCE: 'YOUR_PROJECT_ID:us-central1:merchbay-db'
|
||||
_DB_DATABASE: 'merchbay'
|
||||
_DB_USERNAME: 'laravel_user'
|
||||
# ... other variables
|
||||
```
|
||||
|
||||
## Deployment Steps
|
||||
|
||||
### 1. Set up Cloud Build Trigger
|
||||
|
||||
```bash
|
||||
# Connect your repository to Cloud Build
|
||||
gcloud builds triggers create github \
|
||||
--repo-name=YOUR_REPO_NAME \
|
||||
--repo-owner=YOUR_GITHUB_USERNAME \
|
||||
--branch-pattern="^main$" \
|
||||
--build-config=cloudbuild.yaml
|
||||
|
||||
# Or trigger manually
|
||||
gcloud builds submit --config=cloudbuild.yaml .
|
||||
```
|
||||
|
||||
### 2. Manual Deployment (Alternative)
|
||||
|
||||
```bash
|
||||
# Set your project ID
|
||||
export PROJECT_ID=your-project-id
|
||||
|
||||
# Build and deploy
|
||||
gcloud builds submit --config=cloudbuild.yaml \
|
||||
--substitutions=_PROJECT_ID=$PROJECT_ID,_SERVICE_NAME=merchbay-laravel
|
||||
```
|
||||
|
||||
## Post-deployment Tasks
|
||||
|
||||
### 1. Run Database Migrations
|
||||
|
||||
```bash
|
||||
# Create a one-time job for migrations
|
||||
gcloud run jobs create laravel-migrate \
|
||||
--image=gcr.io/$PROJECT_ID/merchbay-laravel:latest \
|
||||
--region=us-central1 \
|
||||
--set-env-vars="APP_ENV=production" \
|
||||
--set-cloudsql-instances=$PROJECT_ID:us-central1:merchbay-db \
|
||||
--command="php" \
|
||||
--args="artisan,migrate,--force" \
|
||||
--max-retries=1
|
||||
|
||||
# Execute the migration
|
||||
gcloud run jobs execute laravel-migrate --region=us-central1 --wait
|
||||
```
|
||||
|
||||
### 2. Set up Custom Domain (Optional)
|
||||
|
||||
```bash
|
||||
# Map custom domain
|
||||
gcloud run domain-mappings create \
|
||||
--service=merchbay-laravel \
|
||||
--domain=your-domain.com \
|
||||
--region=us-central1
|
||||
```
|
||||
|
||||
### 3. Configure Load Balancer and CDN (Optional)
|
||||
|
||||
For better performance, consider setting up:
|
||||
- Cloud Load Balancer
|
||||
- Cloud CDN for static assets
|
||||
- Cloud Storage for file uploads
|
||||
|
||||
## Environment Variables Reference
|
||||
|
||||
The following environment variables are configured in the Cloud Run service:
|
||||
|
||||
### Application Settings
|
||||
- `APP_ENV=production`
|
||||
- `APP_DEBUG=false`
|
||||
- `APP_KEY` (from Secret Manager)
|
||||
|
||||
### Database Settings
|
||||
- `DB_HOST=127.0.0.1` (Cloud SQL Proxy)
|
||||
- `DB_DATABASE=merchbay`
|
||||
- `DB_USERNAME=laravel_user`
|
||||
- `DB_PASSWORD` (from Secret Manager)
|
||||
|
||||
### Cache & Session
|
||||
- `CACHE_DRIVER=redis` (requires Redis setup)
|
||||
- `SESSION_DRIVER=redis`
|
||||
- `QUEUE_DRIVER=database`
|
||||
|
||||
### PayPal Configuration
|
||||
- `PAYPAL_MODE=live` (or 'sandbox' for testing)
|
||||
- `PAYPAL_LIVE_CLIENT_ID`
|
||||
- `PAYPAL_LIVE_SECRET`
|
||||
- `PAYPAL_SANDBOX_CLIENT_ID`
|
||||
- `PAYPAL_SANDBOX_SECRET`
|
||||
|
||||
### Mail Configuration
|
||||
- `MAIL_DRIVER=smtp`
|
||||
- `MAIL_HOST`
|
||||
- `MAIL_PORT`
|
||||
- `MAIL_USERNAME`
|
||||
- `MAIL_PASSWORD`
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Enable Application Insights
|
||||
|
||||
```bash
|
||||
# Enable Cloud Logging
|
||||
gcloud logging sinks create laravel-logs \
|
||||
bigquery.googleapis.com/projects/$PROJECT_ID/datasets/app_logs
|
||||
```
|
||||
|
||||
### Set up Uptime Monitoring
|
||||
|
||||
```bash
|
||||
# Create uptime check
|
||||
gcloud alpha monitoring uptime create \
|
||||
--display-name="Merchbay Laravel App" \
|
||||
--http-check-path="/" \
|
||||
--hostname=your-service-url.run.app
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **502 Bad Gateway**: Check logs with `gcloud run services logs read merchbay-laravel`
|
||||
2. **Database Connection Issues**: Verify Cloud SQL instance and VPC configuration
|
||||
3. **Memory Issues**: Increase memory allocation in cloudbuild.yaml
|
||||
4. **Timeout Issues**: Increase timeout and check for long-running operations
|
||||
|
||||
### Debugging Commands
|
||||
|
||||
```bash
|
||||
# View service logs
|
||||
gcloud run services logs read merchbay-laravel --region=us-central1
|
||||
|
||||
# Get service details
|
||||
gcloud run services describe merchbay-laravel --region=us-central1
|
||||
|
||||
# Check revisions
|
||||
gcloud run revisions list --service=merchbay-laravel --region=us-central1
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Use Secret Manager** for all sensitive data
|
||||
2. **Enable VPC** for database connections
|
||||
3. **Configure IAM** with least privilege principle
|
||||
4. **Enable Cloud Armor** for DDoS protection
|
||||
5. **Use HTTPS** with managed SSL certificates
|
||||
6. **Regular Updates** for dependencies and base images
|
||||
|
||||
## Cost Optimization
|
||||
|
||||
1. **Set Min Instances to 0** for cost savings
|
||||
2. **Use Appropriate CPU/Memory** settings
|
||||
3. **Implement Caching** (Redis/Memcached)
|
||||
4. **Optimize Images** and use multi-stage builds
|
||||
5. **Monitor Usage** with Cloud Monitoring
|
||||
|
||||
## Support
|
||||
|
||||
For issues specific to:
|
||||
- **Cloud Run**: Check [Cloud Run documentation](https://cloud.google.com/run/docs)
|
||||
- **Laravel**: Check [Laravel documentation](https://laravel.com/docs)
|
||||
- **PayPal Integration**: Check [PayPal developer documentation](https://developer.paypal.com/)
|
||||
@@ -1,125 +0,0 @@
|
||||
# DigiCert SSL Certificate Setup for Production
|
||||
|
||||
## Certificate Files Required
|
||||
|
||||
From DigiCert, you'll receive these files:
|
||||
- `merchbay_com.crt` - Your domain certificate
|
||||
- `merchbay_com.key` - Private key (generated during CSR creation)
|
||||
- `DigiCertCA.crt` - Intermediate certificate
|
||||
- `TrustedRoot.crt` - Root certificate (optional)
|
||||
|
||||
## Step 1: Combine Certificate Chain (on your local machine)
|
||||
|
||||
```bash
|
||||
# Create full chain certificate
|
||||
cat merchbay_com.crt DigiCertCA.crt > merchbay.com.crt
|
||||
|
||||
# Copy private key
|
||||
cp merchbay_com.key merchbay.com.key
|
||||
```
|
||||
|
||||
## Step 2: Upload to Production Server
|
||||
|
||||
```bash
|
||||
# SSH to production server
|
||||
ssh PROD_DEPLOY_USER@PROD_DEPLOY_HOST
|
||||
|
||||
# Create certificates directory
|
||||
sudo mkdir -p /srv/certs
|
||||
sudo chmod 700 /srv/certs
|
||||
|
||||
# Exit SSH, then upload from local machine
|
||||
scp merchbay.com.crt PROD_DEPLOY_USER@PROD_DEPLOY_HOST:/tmp/
|
||||
scp merchbay.com.key PROD_DEPLOY_USER@PROD_DEPLOY_HOST:/tmp/
|
||||
|
||||
# SSH back to server and move files
|
||||
ssh PROD_DEPLOY_USER@PROD_DEPLOY_HOST
|
||||
sudo mv /tmp/merchbay.com.crt /srv/certs/
|
||||
sudo mv /tmp/merchbay.com.key /srv/certs/
|
||||
sudo chmod 600 /srv/certs/*
|
||||
sudo chown root:root /srv/certs/*
|
||||
```
|
||||
|
||||
## Step 3: Upload Traefik Configuration
|
||||
|
||||
```bash
|
||||
# From local machine
|
||||
scp traefik-certs.yml PROD_DEPLOY_USER@PROD_DEPLOY_HOST:/tmp/
|
||||
|
||||
# SSH to server
|
||||
ssh PROD_DEPLOY_USER@PROD_DEPLOY_HOST
|
||||
sudo mkdir -p /srv/traefik
|
||||
sudo mv /tmp/traefik-certs.yml /srv/traefik/dynamic-certs.yml
|
||||
sudo chmod 644 /srv/traefik/dynamic-certs.yml
|
||||
```
|
||||
|
||||
## Step 4: Update Traefik Container
|
||||
|
||||
Ensure your Traefik docker-compose.yml includes:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.10
|
||||
command:
|
||||
- --providers.docker=true
|
||||
- --providers.docker.exposedbydefault=false
|
||||
- --providers.file.filename=/dynamic-certs.yml
|
||||
- --entrypoints.web.address=:80
|
||||
- --entrypoints.websecure.address=:443
|
||||
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /srv/certs:/srv/certs:ro
|
||||
- /srv/traefik/dynamic-certs.yml:/dynamic-certs.yml:ro
|
||||
networks:
|
||||
- traefik-public
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
## Step 5: Restart Traefik
|
||||
|
||||
```bash
|
||||
cd /opt/traefik # or wherever your traefik docker-compose.yml is
|
||||
docker compose restart traefik
|
||||
|
||||
# Verify certificate is loaded
|
||||
docker compose logs traefik | grep -i certificate
|
||||
```
|
||||
|
||||
## Step 6: Deploy merchbay Application
|
||||
|
||||
Once Traefik is configured, deploy merchbay:
|
||||
|
||||
```bash
|
||||
cd /var/www/merchbay
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# Check certificate
|
||||
openssl s_client -connect merchbay.com:443 -servername merchbay.com < /dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
|
||||
|
||||
# Should show:
|
||||
# subject=CN = merchbay.com
|
||||
# issuer=O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
|
||||
# notBefore=...
|
||||
# notAfter=...
|
||||
```
|
||||
|
||||
## Certificate Renewal
|
||||
|
||||
DigiCert certificates typically last 1-2 years. Set a reminder to renew 30 days before expiration and repeat Steps 1-3 and 5.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Never commit `.key` files to git
|
||||
- Keep private keys secure (600 permissions)
|
||||
- Use strong encryption for private key storage
|
||||
- Consider using a certificate management system for automatic renewal
|
||||
100
Dockerfile
Executable file → Normal file
@@ -1,86 +1,40 @@
|
||||
# Use PHP 7.0 with Apache (has native mcrypt support for Laravel 5.0)
|
||||
FROM php:7.0-apache
|
||||
# Use the official PHP image based on Alpine Linux
|
||||
FROM php:5.6-fpm-alpine
|
||||
|
||||
# Update to use archived Debian repositories
|
||||
RUN sed -i 's|deb.debian.org|archive.debian.org|g' /etc/apt/sources.list \
|
||||
&& sed -i 's|security.debian.org|archive.debian.org|g' /etc/apt/sources.list \
|
||||
&& sed -i '/stretch-updates/d' /etc/apt/sources.list
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y --allow-unauthenticated \
|
||||
git \
|
||||
curl \
|
||||
# Install system dependencies and PHP extensions
|
||||
RUN apk --update --no-cache add \
|
||||
nginx \
|
||||
libpng-dev \
|
||||
libxml2-dev \
|
||||
libmcrypt-dev \
|
||||
libjpeg-turbo-dev \
|
||||
freetype-dev \
|
||||
libzip-dev \
|
||||
zip \
|
||||
unzip \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
openssh-client \
|
||||
libmcrypt-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install -j$(nproc) gd
|
||||
&& docker-php-ext-install gd pdo pdo_mysql zip mcrypt
|
||||
|
||||
# Install PHP extensions (mcrypt is built-in for PHP 7.0)
|
||||
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath mcrypt tokenizer zip
|
||||
# Set the working directory in the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Enable Apache mod_rewrite
|
||||
RUN a2enmod rewrite
|
||||
# Copy the Laravel application files to the container
|
||||
COPY . .
|
||||
|
||||
# Install Composer (version 1.x for better compatibility with Laravel 5.0)
|
||||
COPY --from=composer:1.10 /usr/bin/composer /usr/bin/composer
|
||||
# Set appropriate permissions for Laravel storage and bootstrap cache
|
||||
RUN chown -R www-data:www-data storage bootstrap/cache
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Copy existing application directory contents
|
||||
COPY . /var/www/html
|
||||
# Install Laravel dependencies
|
||||
RUN composer install --no-interaction --no-plugins --no-scripts
|
||||
|
||||
# Create storage directories and set permissions
|
||||
RUN mkdir -p storage/framework/views \
|
||||
storage/framework/cache \
|
||||
storage/framework/sessions \
|
||||
storage/logs \
|
||||
bootstrap/cache
|
||||
# Create directory for the socket and set permissions
|
||||
RUN mkdir -p /run/php && chown www-data:www-data /run/php
|
||||
|
||||
# Set proper ownership and permissions
|
||||
RUN chown -R www-data:www-data /var/www/html \
|
||||
&& chmod -R 775 /var/www/html/storage \
|
||||
&& chmod -R 775 /var/www/html/bootstrap/cache
|
||||
# Copy the www.conf file to PHP-FPM pool.d directory
|
||||
# COPY www.conf /usr/local/etc/php-fpm.d/www.conf
|
||||
|
||||
# Create .env file if it doesn't exist
|
||||
RUN if [ ! -f .env ]; then cp .env.example .env; fi
|
||||
|
||||
# Install PHP dependencies (Laravel 5.0 compatible)
|
||||
RUN composer install --no-dev --no-interaction --prefer-dist
|
||||
|
||||
# Generate application key
|
||||
RUN php artisan key:generate || true
|
||||
|
||||
# Run Laravel 5.0 optimization
|
||||
RUN php artisan clear-compiled && php artisan optimize
|
||||
|
||||
# Note: yakpro-po obfuscation requires PHP 7.1+, incompatible with PHP 7.0
|
||||
# For code protection with PHP 7.0, consider:
|
||||
# 1. ionCube Encoder (commercial, most secure)
|
||||
# 2. Keeping source code private and using proper access controls
|
||||
# 3. Using --optimize flag in composer (already done above)
|
||||
|
||||
# Configure Apache DocumentRoot to point to Laravel's public directory
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
|
||||
|
||||
# Suppress Apache ServerName warning
|
||||
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
|
||||
|
||||
# Copy entrypoint script
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Use entrypoint to set up permissions before starting Apache
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["apache2-foreground"]
|
||||
# Expose port 9000 and start php-fpm server
|
||||
EXPOSE 9000
|
||||
CMD ["php-fpm"]
|
||||
71
Dockerfile.alpine
Normal file
@@ -0,0 +1,71 @@
|
||||
# Debug Dockerfile - Let's try the original approach that was working
|
||||
FROM php:5.6-fpm-alpine
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Install system dependencies and PHP extensions
|
||||
RUN apk --update --no-cache add \
|
||||
nginx \
|
||||
libpng-dev \
|
||||
libjpeg-turbo-dev \
|
||||
freetype-dev \
|
||||
libzip-dev \
|
||||
zip \
|
||||
unzip \
|
||||
libmcrypt-dev \
|
||||
curl \
|
||||
git \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install gd pdo pdo_mysql zip mcrypt mbstring
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Copy the Laravel application files to the container
|
||||
COPY . .
|
||||
|
||||
# Set appropriate permissions for Laravel storage and bootstrap cache
|
||||
RUN chown -R www-data:www-data storage bootstrap/cache
|
||||
|
||||
# Install Laravel dependencies
|
||||
RUN composer install --no-interaction --no-plugins --no-scripts --no-dev
|
||||
|
||||
# Create .env file
|
||||
RUN if [ ! -f .env ]; then cp .env.example .env; fi
|
||||
|
||||
# Generate application key
|
||||
RUN php artisan key:generate || true
|
||||
|
||||
# Create directory for the socket and set permissions
|
||||
RUN mkdir -p /run/php && chown www-data:www-data /run/php
|
||||
|
||||
# Configure nginx for Laravel
|
||||
RUN echo 'server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /var/www/public;
|
||||
index index.php index.html index.htm;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}' > /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Create startup script
|
||||
RUN echo '#!/bin/sh
|
||||
php-fpm -D
|
||||
nginx -g "daemon off;"' > /start.sh && chmod +x /start.sh
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Start both PHP-FPM and Nginx
|
||||
CMD ["/start.sh"]
|
||||
39
Dockerfile.basic
Normal file
@@ -0,0 +1,39 @@
|
||||
# Bare minimum working Dockerfile for Laravel 5.0
|
||||
FROM php:5.6-apache
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Install absolute essentials only
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
libmcrypt-dev \
|
||||
&& docker-php-ext-install \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
mcrypt \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable Apache rewrite
|
||||
RUN a2enmod rewrite
|
||||
|
||||
# Configure Apache for Laravel
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
|
||||
# Copy app and set permissions
|
||||
COPY . /var/www/html/
|
||||
RUN chown -R www-data:www-data /var/www/html
|
||||
|
||||
# Basic Laravel setup
|
||||
RUN if [ ! -f .env ]; then cp .env.example .env; fi
|
||||
RUN composer install --no-dev --no-interaction --ignore-platform-reqs
|
||||
RUN php artisan key:generate || true
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["apache2-foreground"]
|
||||
132
Dockerfile.cloudrun
Normal file
@@ -0,0 +1,132 @@
|
||||
# Dockerfile optimized for Google Cloud Run
|
||||
# Use PHP 5.6 with Apache (matches Laravel 5.0 requirements perfectly)
|
||||
FROM php:5.6-apache
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Install system dependencies and PHP extensions required for Laravel
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libpng-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libfreetype6-dev \
|
||||
libmcrypt-dev \
|
||||
zlib1g-dev \
|
||||
zip \
|
||||
unzip \
|
||||
git \
|
||||
curl \
|
||||
libxml2-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
mbstring \
|
||||
zip \
|
||||
gd \
|
||||
xml \
|
||||
mcrypt \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable Apache modules and configure
|
||||
RUN a2enmod rewrite headers
|
||||
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
|
||||
|
||||
# Configure Apache document root for Laravel
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
|
||||
|
||||
# Copy Apache virtual host configuration
|
||||
COPY <<EOF /etc/apache2/sites-available/000-default.conf
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@localhost
|
||||
DocumentRoot /var/www/html/public
|
||||
|
||||
<Directory /var/www/html/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# Logging
|
||||
ErrorLog \${APACHE_LOG_DIR}/error.log
|
||||
CustomLog \${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
# Security headers
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
</VirtualHost>
|
||||
EOF
|
||||
|
||||
# Copy application files
|
||||
COPY . /var/www/html/
|
||||
|
||||
# Fix Git ownership issue for the repository
|
||||
RUN git config --global --add safe.directory /var/www/html || true
|
||||
|
||||
# Install PHP dependencies
|
||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Set proper permissions for Laravel
|
||||
RUN chown -R www-data:www-data /var/www/html \
|
||||
&& chmod -R 755 /var/www/html \
|
||||
&& chmod -R 775 /var/www/html/storage \
|
||||
&& chmod -R 775 /var/www/html/bootstrap/cache
|
||||
|
||||
# Create .env file from .env.example if it doesn't exist
|
||||
RUN if [ ! -f /var/www/html/.env ]; then \
|
||||
cp /var/www/html/.env.example /var/www/html/.env; \
|
||||
fi
|
||||
|
||||
# Switch to www-data user for Laravel commands to avoid ownership issues
|
||||
USER www-data
|
||||
|
||||
# Generate application key (will be overridden by environment variables in Cloud Run)
|
||||
RUN php artisan key:generate || true
|
||||
|
||||
# Clear and cache configuration for production
|
||||
RUN php artisan config:clear || true \
|
||||
&& php artisan route:clear || true \
|
||||
&& php artisan view:clear || true
|
||||
|
||||
# Switch back to root for the remaining setup
|
||||
USER root
|
||||
|
||||
# Create startup script
|
||||
COPY <<EOF /usr/local/bin/start.sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Fix Git ownership issue
|
||||
git config --global --add safe.directory /var/www/html || true
|
||||
|
||||
# Wait for database to be ready (if using Cloud SQL)
|
||||
echo "Starting Laravel application..."
|
||||
|
||||
# Run Laravel optimizations
|
||||
php artisan config:cache || true
|
||||
php artisan route:cache || true
|
||||
php artisan view:cache || true
|
||||
|
||||
# Start Apache in foreground
|
||||
exec apache2-foreground
|
||||
EOF
|
||||
|
||||
RUN chmod +x /usr/local/bin/start.sh
|
||||
|
||||
# Expose port 80 (Cloud Run will map this to 8080)
|
||||
EXPOSE 80
|
||||
|
||||
# Health check for Cloud Run
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD curl -f http://localhost/ || exit 1
|
||||
|
||||
# Use the startup script
|
||||
CMD ["/usr/local/bin/start.sh"]
|
||||
86
Dockerfile.minimal
Normal file
@@ -0,0 +1,86 @@
|
||||
# Minimal Dockerfile for Laravel 5.0 with PHP 5.6
|
||||
FROM php:5.6-apache
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Install only essential system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libmcrypt-dev \
|
||||
libpng-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libfreetype6-dev \
|
||||
zlib1g-dev \
|
||||
zip \
|
||||
unzip \
|
||||
git \
|
||||
curl \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
mcrypt \
|
||||
gd \
|
||||
zip \
|
||||
mbstring \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable Apache modules
|
||||
RUN a2enmod rewrite
|
||||
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
|
||||
|
||||
# Configure Apache document root for Laravel
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
|
||||
|
||||
# Simple Apache configuration
|
||||
RUN echo '<VirtualHost *:80>\n\
|
||||
DocumentRoot /var/www/html/public\n\
|
||||
<Directory /var/www/html/public>\n\
|
||||
AllowOverride All\n\
|
||||
Require all granted\n\
|
||||
</Directory>\n\
|
||||
</VirtualHost>' > /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
# Copy application files
|
||||
COPY . /var/www/html/
|
||||
|
||||
# Fix Git ownership issue
|
||||
RUN git config --global --add safe.directory /var/www/html || true
|
||||
|
||||
# Install PHP dependencies
|
||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Set proper permissions
|
||||
RUN chown -R www-data:www-data /var/www/html \
|
||||
&& chmod -R 755 /var/www/html \
|
||||
&& chmod -R 775 /var/www/html/storage \
|
||||
&& chmod -R 775 /var/www/html/bootstrap/cache
|
||||
|
||||
# Create .env file if it doesn't exist
|
||||
RUN if [ ! -f /var/www/html/.env ]; then \
|
||||
cp /var/www/html/.env.example /var/www/html/.env; \
|
||||
fi
|
||||
|
||||
# Switch to www-data for Laravel commands
|
||||
USER www-data
|
||||
RUN php artisan key:generate || true
|
||||
USER root
|
||||
|
||||
# Create simple startup script
|
||||
RUN echo '#!/bin/bash\n\
|
||||
set -e\n\
|
||||
echo "Starting Laravel application..."\n\
|
||||
exec apache2-foreground' > /usr/local/bin/start.sh \
|
||||
&& chmod +x /usr/local/bin/start.sh
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Start Apache
|
||||
CMD ["/usr/local/bin/start.sh"]
|
||||
75
Dockerfile.simple
Normal file
@@ -0,0 +1,75 @@
|
||||
# Ultra-minimal Dockerfile for Laravel 5.0 with PHP 5.6
|
||||
FROM php:5.6-apache
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Install packages one by one to identify issues
|
||||
RUN apt-get update
|
||||
|
||||
# Install core development tools first
|
||||
RUN apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
zip \
|
||||
unzip
|
||||
|
||||
# Install mcrypt (most important for Laravel 5.0)
|
||||
RUN apt-get install -y libmcrypt-dev \
|
||||
&& docker-php-ext-install mcrypt
|
||||
|
||||
# Install basic PHP extensions
|
||||
RUN docker-php-ext-install \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
mbstring
|
||||
|
||||
# Try to install GD dependencies
|
||||
RUN apt-get install -y \
|
||||
libpng-dev \
|
||||
libjpeg-dev \
|
||||
libfreetype6-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install gd
|
||||
|
||||
# Install zip extension
|
||||
RUN apt-get install -y zlib1g-dev \
|
||||
&& docker-php-ext-install zip
|
||||
|
||||
# Clean up
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable Apache rewrite module
|
||||
RUN a2enmod rewrite
|
||||
|
||||
# Configure Apache
|
||||
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
|
||||
# Copy application files
|
||||
COPY . /var/www/html/
|
||||
|
||||
# Set basic permissions
|
||||
RUN chown -R www-data:www-data /var/www/html \
|
||||
&& chmod -R 755 /var/www/html
|
||||
|
||||
# Create .env file if needed
|
||||
RUN if [ ! -f /var/www/html/.env ]; then \
|
||||
cp /var/www/html/.env.example /var/www/html/.env; \
|
||||
fi
|
||||
|
||||
# Install dependencies without dev packages
|
||||
RUN composer install --no-dev --no-interaction || true
|
||||
|
||||
# Generate Laravel key
|
||||
RUN php artisan key:generate || true
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Start Apache
|
||||
CMD ["apache2-foreground"]
|
||||
60
Dockerfile.test
Normal file
@@ -0,0 +1,60 @@
|
||||
# Test Dockerfile to identify available packages
|
||||
FROM php:5.6-apache
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Update package lists first
|
||||
RUN apt-get update
|
||||
|
||||
# Test each package individually
|
||||
RUN apt-get install -y curl || echo "curl failed"
|
||||
RUN apt-get install -y git || echo "git failed"
|
||||
RUN apt-get install -y zip || echo "zip failed"
|
||||
RUN apt-get install -y unzip || echo "unzip failed"
|
||||
|
||||
# Test mcrypt (most important)
|
||||
RUN apt-get install -y libmcrypt-dev || echo "libmcrypt-dev failed"
|
||||
|
||||
# Test image libraries one by one
|
||||
RUN apt-get install -y libpng-dev || echo "libpng-dev failed"
|
||||
RUN apt-get install -y libjpeg-dev || echo "libjpeg-dev failed"
|
||||
RUN apt-get install -y libfreetype6-dev || echo "libfreetype6-dev failed"
|
||||
|
||||
# Test zip library
|
||||
RUN apt-get install -y zlib1g-dev || echo "zlib1g-dev failed"
|
||||
|
||||
# Try to install PHP extensions
|
||||
RUN docker-php-ext-install mcrypt || echo "mcrypt extension failed"
|
||||
RUN docker-php-ext-install pdo || echo "pdo extension failed"
|
||||
RUN docker-php-ext-install pdo_mysql || echo "pdo_mysql extension failed"
|
||||
RUN docker-php-ext-install mbstring || echo "mbstring extension failed"
|
||||
|
||||
# Test GD configuration
|
||||
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ || echo "gd configure failed"
|
||||
RUN docker-php-ext-install gd || echo "gd extension failed"
|
||||
|
||||
# Test zip extension
|
||||
RUN docker-php-ext-install zip || echo "zip extension failed"
|
||||
|
||||
# Clean up
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Basic Apache setup
|
||||
RUN a2enmod rewrite
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
|
||||
|
||||
# Test copy and basic setup
|
||||
COPY . /var/www/html/
|
||||
RUN chown -R www-data:www-data /var/www/html
|
||||
|
||||
# Test Laravel commands
|
||||
RUN if [ ! -f .env ]; then cp .env.example .env; fi || echo ".env creation failed"
|
||||
RUN composer install --no-dev --no-interaction || echo "composer install failed"
|
||||
RUN php artisan key:generate || echo "key generation failed"
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["apache2-foreground"]
|
||||
@@ -1,133 +0,0 @@
|
||||
# Local Development Setup for Merchbay
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Copy local environment file:**
|
||||
```bash
|
||||
cp .env.local .env
|
||||
```
|
||||
|
||||
2. **Build and start containers:**
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml up -d --build
|
||||
```
|
||||
|
||||
3. **Generate application key:**
|
||||
```bash
|
||||
docker exec merchbay_app_local php artisan key:generate
|
||||
```
|
||||
|
||||
4. **Run migrations:**
|
||||
```bash
|
||||
docker exec merchbay_app_local php artisan migrate
|
||||
```
|
||||
|
||||
5. **Access the application:**
|
||||
- **App:** http://localhost:8080
|
||||
- **phpMyAdmin:** http://localhost:8081
|
||||
- Username: `merchbay`
|
||||
- Password: `secret`
|
||||
|
||||
## Development Commands
|
||||
|
||||
### View logs
|
||||
```bash
|
||||
# Application logs
|
||||
docker exec merchbay_app_local tail -f storage/logs/laravel.log
|
||||
|
||||
# Apache logs
|
||||
docker logs -f merchbay_app_local
|
||||
```
|
||||
|
||||
### Run artisan commands
|
||||
```bash
|
||||
docker exec merchbay_app_local php artisan [command]
|
||||
```
|
||||
|
||||
### Access container shell
|
||||
```bash
|
||||
docker exec -it merchbay_app_local bash
|
||||
```
|
||||
|
||||
### Database access
|
||||
```bash
|
||||
docker exec -it merchbay_db_local mysql -u merchbay -psecret merchbay
|
||||
```
|
||||
|
||||
### Clear caches
|
||||
```bash
|
||||
docker exec merchbay_app_local php artisan cache:clear
|
||||
docker exec merchbay_app_local php artisan config:clear
|
||||
docker exec merchbay_app_local php artisan view:clear
|
||||
```
|
||||
|
||||
### Stop containers
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml down
|
||||
```
|
||||
|
||||
### Stop and remove volumes (clean slate)
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml down -v
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Enable Xdebug (if needed)
|
||||
Add to Dockerfile:
|
||||
```dockerfile
|
||||
RUN pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug
|
||||
```
|
||||
|
||||
### Check container status
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml ps
|
||||
```
|
||||
|
||||
### View all logs
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml logs -f
|
||||
```
|
||||
|
||||
## Hot Reload Development
|
||||
|
||||
For live code changes without rebuilding:
|
||||
- Code changes in `.php` files are reflected immediately (via volume mount)
|
||||
- View changes are reflected immediately
|
||||
- Config/route changes require cache clearing
|
||||
|
||||
## Database Management
|
||||
|
||||
### Import SQL dump
|
||||
```bash
|
||||
docker exec -i merchbay_db_local mysql -u merchbay -psecret merchbay < dump.sql
|
||||
```
|
||||
|
||||
### Export database
|
||||
```bash
|
||||
docker exec merchbay_db_local mysqldump -u merchbay -psecret merchbay > dump.sql
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission issues
|
||||
```bash
|
||||
docker exec merchbay_app_local chown -R www-data:www-data storage bootstrap/cache
|
||||
docker exec merchbay_app_local chmod -R 775 storage bootstrap/cache
|
||||
```
|
||||
|
||||
### Reset everything
|
||||
```bash
|
||||
docker-compose -f docker-compose.local.yml down -v
|
||||
docker rmi merchbay_app:local
|
||||
rm .env
|
||||
cp .env.local .env
|
||||
docker-compose -f docker-compose.local.yml up -d --build
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The local setup uses a separate MySQL container
|
||||
- All code changes are live-mounted for easy development
|
||||
- Mail is logged to `storage/logs/laravel.log` instead of being sent
|
||||
- phpMyAdmin is available for easy database management
|
||||
100
PHP_COMPATIBILITY.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Laravel 5.0 and PHP Compatibility Guide
|
||||
|
||||
## Issue: mcrypt Extension Required
|
||||
|
||||
Laravel 5.0 requires the `mcrypt` PHP extension, which was:
|
||||
|
||||
- **Deprecated** in PHP 7.1
|
||||
- **Removed** in PHP 7.2+
|
||||
|
||||
## Solutions
|
||||
|
||||
### Option 1: Use PHP 5.6 (Current Implementation)
|
||||
|
||||
The `Dockerfile.minimal` has been updated to use PHP 5.6 which is the ideal match for Laravel 5.0.
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Perfect compatibility with Laravel 5.0
|
||||
- Native mcrypt support
|
||||
- All packages available and tested
|
||||
- Matches original development environment
|
||||
|
||||
**Cons:**
|
||||
|
||||
- PHP 5.6 reached end-of-life in December 2018
|
||||
- Security concerns for long-term production use
|
||||
|
||||
### Option 2: Upgrade Laravel (Recommended for Production)
|
||||
Upgrade to Laravel 5.5+ which doesn't require mcrypt.
|
||||
|
||||
```bash
|
||||
# Update composer.json
|
||||
"laravel/framework": "5.8.*"
|
||||
|
||||
# Remove mcrypt dependencies and update encryption
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
### Option 3: Use OpenSSL Instead (Laravel 5.2+)
|
||||
If upgrading Laravel, update encryption configuration:
|
||||
|
||||
```php
|
||||
// config/app.php
|
||||
'cipher' => 'AES-256-CBC',
|
||||
```
|
||||
|
||||
## Current Docker Configuration
|
||||
|
||||
The Dockerfile now uses:
|
||||
|
||||
- **Base Image**: `php:5.6-apache`
|
||||
- **mcrypt Extension**: Native support (no installation issues)
|
||||
- **Other Extensions**: All Laravel 5.0 requirements met
|
||||
- **Package Compatibility**: Perfect match for PHP 5.6
|
||||
|
||||
## Production Recommendations
|
||||
|
||||
For a production deployment, consider:
|
||||
|
||||
1. **Upgrade Laravel** to 5.8 or later (LTS)
|
||||
2. **Use PHP 7.4+** for better performance and security
|
||||
3. **Replace mcrypt** with OpenSSL encryption
|
||||
|
||||
## Quick Upgrade Path (Optional)
|
||||
|
||||
If you want to modernize the application:
|
||||
|
||||
### Step 1: Update composer.json
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"laravel/framework": "5.8.*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Update Dockerfile to use PHP 7.4
|
||||
```dockerfile
|
||||
FROM php:7.4-apache
|
||||
# Remove mcrypt installation
|
||||
```
|
||||
|
||||
### Step 3: Update configuration
|
||||
```bash
|
||||
php artisan key:generate
|
||||
php artisan config:cache
|
||||
```
|
||||
|
||||
## Security Note
|
||||
|
||||
Since PHP 7.1 is end-of-life, monitor for security updates and consider upgrading the Laravel version for long-term production use.
|
||||
|
||||
## Testing the Current Setup
|
||||
|
||||
The current configuration should work with:
|
||||
```bash
|
||||
./start-local.sh
|
||||
```
|
||||
|
||||
This will use PHP 7.1 with mcrypt support for Laravel 5.0 compatibility.
|
||||
@@ -399,8 +399,7 @@ class PaypalController extends Controller
|
||||
public function getTax($cartKey)
|
||||
{
|
||||
$m = new TeamStoreModel;
|
||||
$updated_getSubtotal = $m->getSubtotalNew($cartKey);
|
||||
$original_subtotal = $m->getSubtotal($cartKey); // withoutTanle
|
||||
$updated_getSubtotal = $m->getSubtotal($cartKey);
|
||||
$grouped_item = $m->selectTeamStoreGroupByCartKey($cartKey);
|
||||
|
||||
if (count($grouped_item) <= 0) {
|
||||
@@ -415,11 +414,10 @@ class PaypalController extends Controller
|
||||
|
||||
|
||||
$order_grandtotal = $updated_getSubtotal[0]->Subtotal;
|
||||
$order_subtotal = $original_subtotal[0]->Subtotal;
|
||||
|
||||
|
||||
|
||||
$tax = $order_subtotal * $tax_value;
|
||||
|
||||
$tax = $order_grandtotal * $tax_value;
|
||||
|
||||
return [
|
||||
'tax' => $tax,
|
||||
|
||||
@@ -499,30 +499,6 @@ class TeamStoreController extends Controller
|
||||
'ShippingCostId' => $shipping_cost_id
|
||||
);
|
||||
}
|
||||
} elseif ($product_form == "number-size-form") {
|
||||
|
||||
// $order_names = $post['order_names'];
|
||||
$order_number = $post['order_number'];
|
||||
$order_size = $post['order_size'];
|
||||
|
||||
foreach ($order_size as $key => $val) {
|
||||
$items[] = array(
|
||||
'ProductId' => $product_id,
|
||||
'StoreURL' => $store_url,
|
||||
'StoreId' => $store_id,
|
||||
'FormUsed' => $product_form,
|
||||
'CartKey' => $cartKey,
|
||||
'DesignCode' => $design_code,
|
||||
'ProductURL' => $ProductURL,
|
||||
'ProductName' => $product_name,
|
||||
'Name' => $product_name,
|
||||
'Size' => $order_size[$key],
|
||||
'Number' => $order_number[$key],
|
||||
'Price' => $ProductPrice,
|
||||
'Quantity' => 1,
|
||||
'ShippingCostId' => $shipping_cost_id
|
||||
);
|
||||
}
|
||||
} elseif ($product_form == "number-form") {
|
||||
|
||||
$order_number = $post['order_number'];
|
||||
@@ -978,7 +954,6 @@ class TeamStoreController extends Controller
|
||||
'shippingFee' => number_format($shippingFee, 2),
|
||||
'total' => number_format($finalSubTotal + $shippingFee + $tax["tax"], 2),
|
||||
'subtotal' => number_format($finalSubTotal, 2),
|
||||
'tax' => $tax["tax"],
|
||||
'remaining_shippingfee' => number_format(99 - $finalSubTotal, 2)
|
||||
));
|
||||
} else {
|
||||
|
||||
@@ -34,10 +34,10 @@ class UserController extends Controller
|
||||
|
||||
$post_data = array(
|
||||
'isStoreOwner' => true,
|
||||
'store_order' => isset($countStoreOrder[0]->count_order) ? $countStoreOrder[0]->count_order : 0,
|
||||
'store_income' => isset($storeIncome[0]->store_income) ? $storeIncome[0]->store_income : 0,
|
||||
'store_product_count' => isset($countStoreProduct[0]->store_product_count) ? $countStoreProduct[0]->store_product_count : 0,
|
||||
'store_published_product' => isset($countStorePublishedProduct[0]->store_published_product) ? $countStorePublishedProduct[0]->store_published_product : 0
|
||||
'store_order' => $countStoreOrder[0]->count_order,
|
||||
'store_income' => $storeIncome[0]->store_income,
|
||||
'store_product_count' => $countStoreProduct[0]->store_product_count,
|
||||
'store_published_product' => $countStorePublishedProduct[0]->store_published_product
|
||||
);
|
||||
} else {
|
||||
$post_data = array(
|
||||
@@ -348,16 +348,14 @@ class UserController extends Controller
|
||||
$newTeamStoreModel = new TeamStoreModel;
|
||||
|
||||
$product_array = $newTeamStoreModel->selectTeamStoreProducts('ProductURL', $url);
|
||||
$roster = $newUserModel->getRoster($product_array[0]->Id);
|
||||
$thumbnails_array = $newTeamStoreModel->getThumbnails($product_array[0]->Id);
|
||||
$available_size = explode(",", $product_array[0]->AvailableSizes);
|
||||
$shipping_cost = $newUserModel->selectShippingCost();
|
||||
|
||||
return view('user-layouts.view-store-item')->with('product_array', $product_array)
|
||||
->with('available_size', $available_size)
|
||||
->with('thumbnails_array', $thumbnails_array)
|
||||
->with('shipping_cost', $shipping_cost)
|
||||
->with('roster', $roster);
|
||||
|
||||
->with('shipping_cost', $shipping_cost);
|
||||
}
|
||||
|
||||
|
||||
@@ -1346,76 +1344,4 @@ class UserController extends Controller
|
||||
|
||||
return $array_address_book;
|
||||
}
|
||||
|
||||
function roster(Request $request)
|
||||
{
|
||||
$UserModel = new UserModel;
|
||||
$post = $request->all();
|
||||
|
||||
$response = $UserModel->insertRoster($post['data']);
|
||||
|
||||
if($response) {
|
||||
return response()->json(array(
|
||||
'status' => true,
|
||||
'message' => "Roster is successfully saved."
|
||||
));
|
||||
}
|
||||
|
||||
return response()->json(array(
|
||||
'status' => false,
|
||||
'message' => "Something went wrong. Please try again"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
function deleteRoster(Request $request) {
|
||||
$UserModel = new UserModel;
|
||||
$post = $request->all();
|
||||
|
||||
$response = $UserModel->deleteRoster($post['data']);
|
||||
|
||||
if($response) {
|
||||
return response()->json(array(
|
||||
'status' => true,
|
||||
'message' => "Roster is successfully deleted."
|
||||
));
|
||||
}
|
||||
|
||||
return response()->json(array(
|
||||
'status' => false,
|
||||
'message' => "Something went wrong. Please try again"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
function rosterUpdate(Request $request)
|
||||
{
|
||||
$UserModel = new UserModel;
|
||||
$post = $request->all();
|
||||
|
||||
$response = $UserModel->updateRoster($post['data']);
|
||||
|
||||
if($response) {
|
||||
return response()->json(array(
|
||||
'status' => true,
|
||||
'message' => "Roster is successfully updated."
|
||||
));
|
||||
}
|
||||
|
||||
return response()->json(array(
|
||||
'status' => false,
|
||||
'message' => "Something went wrong. Please try again"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
function getCurrentRoster(Request $request) {
|
||||
$productId = $request->query('product-id');
|
||||
$newUserModel = new UserModel;
|
||||
$roster = $newUserModel->getRoster($productId);
|
||||
return response()->json($roster);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,11 +149,6 @@ Route::group(['middleware' => 'normaluser'], function () {
|
||||
|
||||
|
||||
Route::post('user/store-items/personal-design', 'user\UserController@saveNewItemFromDesigner');
|
||||
|
||||
Route::post('user/roster', 'user\UserController@roster');
|
||||
Route::get('user/roster', 'user\UserController@getCurrentRoster');
|
||||
Route::post('user/roster-delete', 'user\UserController@deleteRoster');
|
||||
Route::post('user/roster-update', 'user\UserController@rosterUpdate');
|
||||
});
|
||||
|
||||
Route::group(['middleware' => 'auth'], function () {
|
||||
|
||||
@@ -189,16 +189,6 @@ class TeamStoreModel extends Model
|
||||
return $i;
|
||||
}
|
||||
|
||||
function getSubtotalNew($cartKey)
|
||||
{
|
||||
|
||||
$i = DB::table('cart_tmp')->select(DB::raw('SUM(Quantity * Price) AS Subtotal'))
|
||||
->where('CartKey', '=', $cartKey)
|
||||
// ->where('VoucherId', '=', null)
|
||||
->get();
|
||||
return $i;
|
||||
}
|
||||
|
||||
function updateStoreItem($data, $url)
|
||||
{
|
||||
$i = DB::table('teamstore_products')->where('ProductURL', $url)
|
||||
|
||||
@@ -425,44 +425,4 @@ class UserModel extends Model
|
||||
->update($data);
|
||||
return $i;
|
||||
}
|
||||
|
||||
function insertRoster($data) {
|
||||
$i = DB::table('roster')
|
||||
->insert($data);
|
||||
return $i;
|
||||
}
|
||||
|
||||
function getRoster($productId)
|
||||
{
|
||||
$i = DB::table('roster')
|
||||
->where('ProductId', $productId)
|
||||
->get();
|
||||
return $i;
|
||||
}
|
||||
|
||||
function deleteRoster($idArray)
|
||||
{
|
||||
$deletedRows = DB::table('roster')
|
||||
->whereIn('Id', $idArray) // Replace 'id' with the actual column name if different
|
||||
->delete();
|
||||
|
||||
return $deletedRows; // Returns the number of rows deleted
|
||||
}
|
||||
|
||||
function updateRoster($data)
|
||||
{
|
||||
$updatedRows = 0;
|
||||
|
||||
foreach ($data as $item) {
|
||||
// Assuming each item contains an 'id' and the fields to update
|
||||
$id = $item['Id'];
|
||||
unset($item['Id']); // Remove 'id' from the update data
|
||||
|
||||
$updatedRows += DB::table('roster')
|
||||
->where('Id', $id)
|
||||
->update($item);
|
||||
}
|
||||
|
||||
return $updatedRows; // Returns the total number of rows updated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,7 @@ class AppServiceProvider extends ServiceProvider {
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
// Force HTTPS URLs when behind a proxy (Traefik)
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
|
||||
\URL::forceSchema('https');
|
||||
}
|
||||
|
||||
//
|
||||
Blade::extend(function($value) {
|
||||
return preg_replace('/\@define(.+)/', '<?php ${1}; ?>', $value);
|
||||
});
|
||||
|
||||
156
cloudbuild.yaml
Normal file
@@ -0,0 +1,156 @@
|
||||
# Google Cloud Build configuration for Laravel 5 application deployment to Cloud Run
|
||||
steps:
|
||||
# Step 1: Build the Docker image
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'build'
|
||||
- '-t'
|
||||
- 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA'
|
||||
- '-t'
|
||||
- 'gcr.io/$PROJECT_ID/merchbay-laravel:latest'
|
||||
- '-f'
|
||||
- 'Dockerfile.simple'
|
||||
- '.'
|
||||
id: 'build-image'
|
||||
|
||||
# Step 2: Push the Docker image to Google Container Registry
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'push'
|
||||
- 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA'
|
||||
id: 'push-image'
|
||||
waitFor: ['build-image']
|
||||
|
||||
# Step 3: Push the latest tag as well
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'push'
|
||||
- 'gcr.io/$PROJECT_ID/merchbay-laravel:latest'
|
||||
id: 'push-latest'
|
||||
waitFor: ['build-image']
|
||||
|
||||
# Step 4: Run database migrations (optional - only if you have Cloud SQL configured)
|
||||
# Uncomment and configure if you need to run migrations
|
||||
# - name: 'gcr.io/cloud-builders/gcloud'
|
||||
# entrypoint: 'bash'
|
||||
# args:
|
||||
# - '-c'
|
||||
# - |
|
||||
# gcloud run jobs create laravel-migrate \
|
||||
# --image=gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA \
|
||||
# --region=$_REGION \
|
||||
# --set-env-vars="APP_ENV=production,APP_KEY=$_APP_KEY,DB_HOST=$_DB_HOST,DB_DATABASE=$_DB_DATABASE,DB_USERNAME=$_DB_USERNAME,DB_PASSWORD=$_DB_PASSWORD" \
|
||||
# --set-cloudsql-instances=$_CLOUDSQL_INSTANCE \
|
||||
# --command="php" \
|
||||
# --args="artisan,migrate,--force" \
|
||||
# --max-retries=1 \
|
||||
# --replace || true
|
||||
# gcloud run jobs execute laravel-migrate --region=$_REGION --wait
|
||||
# id: 'run-migrations'
|
||||
# waitFor: ['push-image']
|
||||
|
||||
# Step 5: Deploy to Cloud Run
|
||||
- name: 'gcr.io/cloud-builders/gcloud'
|
||||
args:
|
||||
- 'run'
|
||||
- 'deploy'
|
||||
- '$_SERVICE_NAME'
|
||||
- '--image'
|
||||
- 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA'
|
||||
- '--region'
|
||||
- '$_REGION'
|
||||
- '--platform'
|
||||
- 'managed'
|
||||
- '--allow-unauthenticated'
|
||||
- '--port'
|
||||
- '8080'
|
||||
- '--memory'
|
||||
- '$_MEMORY'
|
||||
- '--cpu'
|
||||
- '$_CPU'
|
||||
- '--timeout'
|
||||
- '$_TIMEOUT'
|
||||
- '--concurrency'
|
||||
- '$_CONCURRENCY'
|
||||
- '--min-instances'
|
||||
- '$_MIN_INSTANCES'
|
||||
- '--max-instances'
|
||||
- '$_MAX_INSTANCES'
|
||||
- '--set-env-vars'
|
||||
- 'APP_ENV=production,APP_DEBUG=false,APP_KEY=$_APP_KEY,DB_HOST=$_DB_HOST,DB_DATABASE=$_DB_DATABASE,DB_USERNAME=$_DB_USERNAME,DB_PASSWORD=$_DB_PASSWORD,CACHE_DRIVER=redis,SESSION_DRIVER=redis,QUEUE_DRIVER=database,PAYPAL_MODE=$_PAYPAL_MODE,PAYPAL_LIVE_CLIENT_ID=$_PAYPAL_LIVE_CLIENT_ID,PAYPAL_LIVE_SECRET=$_PAYPAL_LIVE_SECRET,PAYPAL_SANDBOX_CLIENT_ID=$_PAYPAL_SANDBOX_CLIENT_ID,PAYPAL_SANDBOX_SECRET=$_PAYPAL_SANDBOX_SECRET,MAIL_DRIVER=$_MAIL_DRIVER,MAIL_HOST=$_MAIL_HOST,MAIL_PORT=$_MAIL_PORT,MAIL_USERNAME=$_MAIL_USERNAME,MAIL_PASSWORD=$_MAIL_PASSWORD,GOOGLE_ANALYTICS_VIEW_ID=$_GOOGLE_ANALYTICS_VIEW_ID'
|
||||
- '--set-cloudsql-instances'
|
||||
- '$_CLOUDSQL_INSTANCE'
|
||||
- '--vpc-connector'
|
||||
- '$_VPC_CONNECTOR'
|
||||
- '--add-cloudsql-instances'
|
||||
- '$_CLOUDSQL_INSTANCE'
|
||||
id: 'deploy-service'
|
||||
waitFor: ['push-image']
|
||||
|
||||
# Substitution variables - you can override these in your Cloud Build trigger
|
||||
substitutions:
|
||||
# Service configuration
|
||||
_SERVICE_NAME: 'merchbay-laravel'
|
||||
_REGION: 'us-central1'
|
||||
|
||||
# Resource limits
|
||||
_MEMORY: '1Gi'
|
||||
_CPU: '1000m'
|
||||
_TIMEOUT: '300s'
|
||||
_CONCURRENCY: '80'
|
||||
_MIN_INSTANCES: '0'
|
||||
_MAX_INSTANCES: '10'
|
||||
|
||||
# Database configuration (Cloud SQL)
|
||||
_CLOUDSQL_INSTANCE: 'YOUR_PROJECT_ID:REGION:INSTANCE_NAME'
|
||||
_DB_HOST: '127.0.0.1'
|
||||
_DB_DATABASE: 'merchbay'
|
||||
_DB_USERNAME: 'laravel_user'
|
||||
_DB_PASSWORD: 'YOUR_DB_PASSWORD'
|
||||
|
||||
# VPC configuration (if needed)
|
||||
_VPC_CONNECTOR: 'projects/YOUR_PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME'
|
||||
|
||||
# Application configuration
|
||||
_APP_KEY: 'base64:YOUR_APP_KEY_HERE'
|
||||
|
||||
# PayPal configuration
|
||||
_PAYPAL_MODE: 'live'
|
||||
_PAYPAL_LIVE_CLIENT_ID: 'YOUR_PAYPAL_LIVE_CLIENT_ID'
|
||||
_PAYPAL_LIVE_SECRET: 'YOUR_PAYPAL_LIVE_SECRET'
|
||||
_PAYPAL_SANDBOX_CLIENT_ID: 'YOUR_PAYPAL_SANDBOX_CLIENT_ID'
|
||||
_PAYPAL_SANDBOX_SECRET: 'YOUR_PAYPAL_SANDBOX_SECRET'
|
||||
|
||||
# Mail configuration
|
||||
_MAIL_DRIVER: 'smtp'
|
||||
_MAIL_HOST: 'smtp.gmail.com'
|
||||
_MAIL_PORT: '587'
|
||||
_MAIL_USERNAME: 'your-email@domain.com'
|
||||
_MAIL_PASSWORD: 'your-app-password'
|
||||
|
||||
# Google Analytics
|
||||
_GOOGLE_ANALYTICS_VIEW_ID: 'YOUR_GA_VIEW_ID'
|
||||
|
||||
# Build options
|
||||
options:
|
||||
# Use a more powerful machine for faster builds
|
||||
machineType: 'E2_HIGHCPU_8'
|
||||
|
||||
# Enable detailed logging
|
||||
logging: CLOUD_LOGGING_ONLY
|
||||
|
||||
# Build timeout
|
||||
timeout: '1200s'
|
||||
|
||||
# Store build logs in Cloud Logging
|
||||
logsBucket: 'gs://YOUR_PROJECT_ID_cloudbuild-logs'
|
||||
|
||||
# Available logs for debugging
|
||||
availableSecrets:
|
||||
secretManager:
|
||||
- versionName: 'projects/YOUR_PROJECT_ID/secrets/APP_KEY/versions/latest'
|
||||
env: 'APP_KEY'
|
||||
- versionName: 'projects/YOUR_PROJECT_ID/secrets/DB_PASSWORD/versions/latest'
|
||||
env: 'DB_PASSWORD'
|
||||
- versionName: 'projects/YOUR_PROJECT_ID/secrets/PAYPAL_LIVE_SECRET/versions/latest'
|
||||
env: 'PAYPAL_LIVE_SECRET'
|
||||
@@ -1,58 +0,0 @@
|
||||
services:
|
||||
app:
|
||||
image: merchbay:dev
|
||||
container_name: merchbay_app_dev
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- APP_ENV=${APP_ENV:-development}
|
||||
- APP_DEBUG=${APP_DEBUG:-true}
|
||||
- APP_URL=${APP_URL:-https://dev.merchbay.app}
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_DATABASE=${DB_DATABASE}
|
||||
- DB_USERNAME=${DB_USERNAME}
|
||||
- DB_PASSWORD=${DB_PASSWORD}
|
||||
- PROD_PRIVATE=${PROD_PRIVATE}
|
||||
- IMAGES_URL=${IMAGES_URL}
|
||||
- UPLOAD_URL=${UPLOAD_URL}
|
||||
- FORCE_HTTPS=true
|
||||
- MAIL_DRIVER=${MAIL_DRIVER}
|
||||
- MAIL_HOST=${MAIL_HOST}
|
||||
- MAIL_PORT=${MAIL_PORT}
|
||||
- MAIL_USERNAME=${MAIL_USERNAME}
|
||||
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
- MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
|
||||
- CAPTCHA_SITE_KEY=${CAPTCHA_SITE_KEY}
|
||||
- CAPTCHA_SECRET_KEY=${CAPTCHA_SECRET_KEY}
|
||||
- ANALYTICS_SITE_ID=${ANALYTICS_SITE_ID}
|
||||
- ANALYTICS_CLIENT_ID=${ANALYTICS_CLIENT_ID}
|
||||
- ANALYTICS_SERVICE_EMAIL=${ANALYTICS_SERVICE_EMAIL}
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./public/uploads:/var/www/html/public/uploads
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Development environment (dev.merchbay.app)
|
||||
- "traefik.http.routers.merchbay-dev.rule=Host(`dev.merchbay.app`)"
|
||||
- "traefik.http.routers.merchbay-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.merchbay-dev.tls=true"
|
||||
- "traefik.http.routers.merchbay-dev.tls.certresolver=le"
|
||||
- "traefik.http.services.merchbay-dev.loadbalancer.server.port=80"
|
||||
# HTTP to HTTPS redirect
|
||||
- "traefik.http.routers.merchbay-dev-http.rule=Host(`dev.merchbay.app`)"
|
||||
- "traefik.http.routers.merchbay-dev-http.entrypoints=web"
|
||||
- "traefik.http.routers.merchbay-dev-http.middlewares=https-redirect"
|
||||
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
|
||||
networks:
|
||||
- traefik-public
|
||||
- crew-app-net
|
||||
- default
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
crew-app-net:
|
||||
external: true
|
||||
default:
|
||||
driver: bridge
|
||||
@@ -1,81 +1,75 @@
|
||||
services:
|
||||
db:
|
||||
image: mariadb:10.6
|
||||
platform: linux/arm64
|
||||
container_name: merchbay_db_local
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_DATABASE: merchbay
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_USER: merchbay
|
||||
MYSQL_PASSWORD: secret
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
networks:
|
||||
- merchbay-local
|
||||
# Docker Compose for local development and testing
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: merchbay_app_local
|
||||
restart: unless-stopped
|
||||
dockerfile: Dockerfile.basic
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
- APP_ENV=local
|
||||
- APP_DEBUG=true
|
||||
- APP_URL=http://localhost:8080
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=db
|
||||
- DB_PORT=3306
|
||||
- APP_KEY=base64:your-app-key-here
|
||||
- DB_HOST=mysql
|
||||
- DB_DATABASE=merchbay
|
||||
- DB_USERNAME=merchbay
|
||||
- DB_USERNAME=laravel_user
|
||||
- DB_PASSWORD=secret
|
||||
- PROD_PRIVATE=http://localhost:8080
|
||||
- IMAGES_URL=http://localhost:8080
|
||||
- UPLOAD_URL=http://localhost:8080/uploads/
|
||||
- CACHE_DRIVER=file
|
||||
- SESSION_DRIVER=file
|
||||
- REDIS_HOST=redis
|
||||
- QUEUE_DRIVER=sync
|
||||
- PAYPAL_MODE=sandbox
|
||||
- PAYPAL_SANDBOX_CLIENT_ID=your-sandbox-client-id
|
||||
- PAYPAL_SANDBOX_SECRET=your-sandbox-secret
|
||||
- MAIL_DRIVER=log
|
||||
- MAIL_HOST=localhost
|
||||
- MAIL_PORT=1025
|
||||
- MAIL_USERNAME=null
|
||||
- MAIL_PASSWORD=null
|
||||
- MAIL_ENCRYPTION=null
|
||||
- CAPTCHA_SITE_KEY=test_key
|
||||
- CAPTCHA_SECRET_KEY=test_secret
|
||||
- ANALYTICS_SITE_ID=
|
||||
- ANALYTICS_CLIENT_ID=
|
||||
- ANALYTICS_SERVICE_EMAIL=
|
||||
volumes:
|
||||
- ./:/var/www/html
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./public/uploads:/var/www/html/public/uploads
|
||||
- ./bootstrap/cache:/var/www/html/bootstrap/cache
|
||||
depends_on:
|
||||
- db
|
||||
- mysql
|
||||
- redis
|
||||
networks:
|
||||
- merchbay-local
|
||||
- app-network
|
||||
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
- MYSQL_DATABASE=merchbay
|
||||
- MYSQL_USER=laravel_user
|
||||
- MYSQL_PASSWORD=secret
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
phpmyadmin:
|
||||
image: arm64v8/phpmyadmin
|
||||
platform: linux/arm64
|
||||
container_name: merchbay_phpmyadmin
|
||||
restart: unless-stopped
|
||||
image: phpmyadmin/phpmyadmin
|
||||
environment:
|
||||
- PMA_HOST=mysql
|
||||
- PMA_USER=root
|
||||
- PMA_PASSWORD=root
|
||||
ports:
|
||||
- "8081:80"
|
||||
environment:
|
||||
PMA_HOST: db
|
||||
PMA_PORT: 3306
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
depends_on:
|
||||
- db
|
||||
- mysql
|
||||
networks:
|
||||
- merchbay-local
|
||||
|
||||
networks:
|
||||
merchbay-local:
|
||||
driver: bridge
|
||||
- app-network
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
mysql_data:
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
services:
|
||||
app:
|
||||
image: merchbay:latest
|
||||
container_name: merchbay_app_prod
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- APP_ENV=${APP_ENV:-production}
|
||||
- APP_DEBUG=${APP_DEBUG:-false}
|
||||
- APP_URL=${APP_URL:-https://merchbay.com}
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_DATABASE=${DB_DATABASE}
|
||||
- DB_USERNAME=${DB_USERNAME}
|
||||
- DB_PASSWORD=${DB_PASSWORD}
|
||||
- PROD_PRIVATE=${PROD_PRIVATE}
|
||||
- IMAGES_URL=${IMAGES_URL}
|
||||
- UPLOAD_URL=${UPLOAD_URL}
|
||||
- FORCE_HTTPS=true
|
||||
- MAIL_DRIVER=${MAIL_DRIVER}
|
||||
- MAIL_HOST=${MAIL_HOST}
|
||||
- MAIL_PORT=${MAIL_PORT}
|
||||
- MAIL_USERNAME=${MAIL_USERNAME}
|
||||
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
- MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
|
||||
- CAPTCHA_SITE_KEY=${CAPTCHA_SITE_KEY}
|
||||
- CAPTCHA_SECRET_KEY=${CAPTCHA_SECRET_KEY}
|
||||
- ANALYTICS_SITE_ID=${ANALYTICS_SITE_ID}
|
||||
- ANALYTICS_CLIENT_ID=${ANALYTICS_CLIENT_ID}
|
||||
- ANALYTICS_SERVICE_EMAIL=${ANALYTICS_SERVICE_EMAIL}
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./public/uploads:/var/www/html/public/uploads
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Production environment (merchbay.com) - Uses DigiCert SSL
|
||||
- "traefik.http.routers.merchbay-prod.rule=Host(`merchbay.com`) || Host(`www.merchbay.com`)"
|
||||
- "traefik.http.routers.merchbay-prod.entrypoints=websecure"
|
||||
- "traefik.http.routers.merchbay-prod.tls=true"
|
||||
- "traefik.http.services.merchbay-prod.loadbalancer.server.port=80"
|
||||
# HTTP to HTTPS redirect
|
||||
- "traefik.http.routers.merchbay-prod-http.rule=Host(`merchbay.com`) || Host(`www.merchbay.com`)"
|
||||
- "traefik.http.routers.merchbay-prod-http.entrypoints=web"
|
||||
- "traefik.http.routers.merchbay-prod-http.middlewares=https-redirect"
|
||||
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
|
||||
networks:
|
||||
- traefik-public
|
||||
- crew-app-net
|
||||
- default
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
crew-app-net:
|
||||
external: true
|
||||
default:
|
||||
driver: bridge
|
||||
103
docker-compose.yml
Executable file → Normal file
@@ -1,74 +1,45 @@
|
||||
# ⚠️ DEPRECATED: Use docker-compose.dev.yml or docker-compose.prod.yml instead
|
||||
# This file is kept for reference only
|
||||
#
|
||||
# For development: docker-compose.dev.yml (dev.merchbay.app)
|
||||
# For production: docker-compose.prod.yml (merchbay.com)
|
||||
# For local dev: docker-compose.local.yml (localhost:8080)
|
||||
|
||||
version: '3'
|
||||
services:
|
||||
|
||||
#PHP Service
|
||||
app:
|
||||
image: merchbay:latest
|
||||
container_name: merchbay_app
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: digitalocean.com/php
|
||||
container_name: app
|
||||
restart: unless-stopped
|
||||
tty: true
|
||||
environment:
|
||||
- APP_ENV=${APP_ENV:-production}
|
||||
- APP_DEBUG=${APP_DEBUG:-false}
|
||||
- APP_URL=${APP_URL:-http://localhost}
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_DATABASE=${DB_DATABASE}
|
||||
- DB_USERNAME=${DB_USERNAME}
|
||||
- DB_PASSWORD=${DB_PASSWORD}
|
||||
- PROD_PRIVATE=${PROD_PRIVATE}
|
||||
- IMAGES_URL=${IMAGES_URL}
|
||||
- UPLOAD_URL=${UPLOAD_URL}
|
||||
- FORCE_HTTPS=true
|
||||
- MAIL_DRIVER=${MAIL_DRIVER}
|
||||
- MAIL_HOST=${MAIL_HOST}
|
||||
- MAIL_PORT=${MAIL_PORT}
|
||||
- MAIL_USERNAME=${MAIL_USERNAME}
|
||||
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
- MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
|
||||
- CAPTCHA_SITE_KEY=${CAPTCHA_SITE_KEY}
|
||||
- CAPTCHA_SECRET_KEY=${CAPTCHA_SECRET_KEY}
|
||||
- ANALYTICS_SITE_ID=${ANALYTICS_SITE_ID}
|
||||
- ANALYTICS_CLIENT_ID=${ANALYTICS_CLIENT_ID}
|
||||
- ANALYTICS_SERVICE_EMAIL=${ANALYTICS_SERVICE_EMAIL}
|
||||
SERVICE_NAME: app
|
||||
SERVICE_TAGS: dev
|
||||
working_dir: /var/www
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./public/uploads:/var/www/html/public/uploads
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Development environment (dev.merchbay.app)
|
||||
- "traefik.http.routers.merchbay-dev.rule=Host(`dev.merchbay.app`)"
|
||||
- "traefik.http.routers.merchbay-dev.entrypoints=websecure"
|
||||
- "traefik.http.routers.merchbay-dev.tls=true"
|
||||
- "traefik.http.routers.merchbay-dev.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.merchbay-dev.loadbalancer.server.port=80"
|
||||
# Production environment (merchbay.com) - Uses DigiCert SSL
|
||||
- "traefik.http.routers.merchbay-prod.rule=Host(`merchbay.com`) || Host(`www.merchbay.com`)"
|
||||
- "traefik.http.routers.merchbay-prod.entrypoints=websecure"
|
||||
- "traefik.http.routers.merchbay-prod.tls=true"
|
||||
- "traefik.http.services.merchbay-prod.loadbalancer.server.port=80"
|
||||
# HTTP to HTTPS redirect - Development
|
||||
- "traefik.http.routers.merchbay-dev-http.rule=Host(`dev.merchbay.app`)"
|
||||
- "traefik.http.routers.merchbay-dev-http.entrypoints=web"
|
||||
- "traefik.http.routers.merchbay-dev-http.middlewares=https-redirect"
|
||||
# HTTP to HTTPS redirect - Production
|
||||
- "traefik.http.routers.merchbay-prod-http.rule=Host(`merchbay.com`) || Host(`www.merchbay.com`)"
|
||||
- "traefik.http.routers.merchbay-prod-http.entrypoints=web"
|
||||
- "traefik.http.routers.merchbay-prod-http.middlewares=https-redirect"
|
||||
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
|
||||
- ./:/var/www
|
||||
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
|
||||
networks:
|
||||
- traefik-public
|
||||
- crew-app-net
|
||||
- default
|
||||
- app-network
|
||||
|
||||
#Nginx Service
|
||||
webserver:
|
||||
image: nginx:alpine
|
||||
container_name: webserver
|
||||
restart: unless-stopped
|
||||
tty: true
|
||||
ports:
|
||||
- "10003:80"
|
||||
- "10443:443"
|
||||
volumes:
|
||||
- ./:/var/www
|
||||
- ./nginx/conf.d/:/etc/nginx/conf.d/
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
#Docker Networks
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
crew-app-net:
|
||||
external: true
|
||||
default:
|
||||
driver: bridge
|
||||
app-network:
|
||||
driver: bridge
|
||||
#Volumes
|
||||
volumes:
|
||||
dbdata:
|
||||
driver: local
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Create storage directory structure if it doesn't exist
|
||||
mkdir -p storage/framework/views
|
||||
mkdir -p storage/framework/cache
|
||||
mkdir -p storage/framework/sessions
|
||||
mkdir -p storage/logs
|
||||
mkdir -p storage/app/public
|
||||
mkdir -p bootstrap/cache
|
||||
|
||||
# Set proper permissions
|
||||
chown -R www-data:www-data storage bootstrap/cache
|
||||
chmod -R 775 storage bootstrap/cache
|
||||
|
||||
# Execute the main command
|
||||
exec "$@"
|
||||
0
favicon.ico
Executable file → Normal file
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
40
nginx/conf.d/app.conf
Executable file → Normal file
@@ -3,37 +3,29 @@ server {
|
||||
index index.php index.html;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /var/www;
|
||||
index index.php index.html;
|
||||
root /var/www/public;
|
||||
|
||||
location / {
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE, HEAD';
|
||||
add_header 'Access-Control-Max-Age' '1728000';
|
||||
add_header 'Access-Control-Allow-Headers' '*';
|
||||
#add_header 'Content-Type: text/plain; charset=UTF-8';
|
||||
#add_header 'Content-Length: 0';
|
||||
return 204;
|
||||
}
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_index index.php;
|
||||
fastcgi_pass app:9000;
|
||||
|
||||
include fastcgi_params;
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
||||
fastcgi_pass app:9000;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~* \.(css|less|js|jpg|png|gif)$ {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
expires 0;
|
||||
expires 0;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
}
|
||||
|
||||
}
|
||||
0
php/local.ini
Executable file → Normal file
0
public/api/canada.json
Executable file → Normal file
0
public/api/usa.json
Executable file → Normal file
0
public/api/usaCities.old.json
Executable file → Normal file
0
public/assets/css/jquery-ui.css
vendored
Executable file → Normal file
0
public/assets/files/Terms of Use.pdf
Executable file → Normal file
0
public/assets/js/jquery-ui.js
vendored
Executable file → Normal file
0
public/images/MERCHBAY-LOGO.png
Executable file → Normal file
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
public/images/merchbay-black.png
Executable file → Normal file
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
0
public/images/merchbay-white.png
Executable file → Normal file
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
176
readme.md
@@ -1,171 +1,23 @@
|
||||
# MerchBay
|
||||
## Laravel PHP Framework
|
||||
|
||||
A custom merchandise and apparel design platform built with Laravel 5.0, enabling users to create, customize, and order personalized products.
|
||||
[](https://travis-ci.org/laravel/framework)
|
||||
[](https://packagist.org/packages/laravel/framework)
|
||||
[](https://packagist.org/packages/laravel/framework)
|
||||
[](https://packagist.org/packages/laravel/framework)
|
||||
[](https://packagist.org/packages/laravel/framework)
|
||||
|
||||
## 🚀 Tech Stack
|
||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Laravel attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as authentication, routing, sessions, queueing, and caching.
|
||||
|
||||
- **Framework:** Laravel 5.0
|
||||
- **PHP:** 7.0 with native mcrypt support
|
||||
- **Web Server:** Apache 2.4
|
||||
- **Database:** MySQL
|
||||
- **Container:** Docker with Apache
|
||||
- **Reverse Proxy:** Traefik (for SSL/TLS and routing)
|
||||
Laravel is accessible, yet powerful, providing powerful tools needed for large, robust applications. A superb inversion of control container, expressive migration system, and tightly integrated unit testing support give you the tools you need to build any application with which you are tasked.
|
||||
|
||||
## 📋 Prerequisites
|
||||
## Official Documentation
|
||||
|
||||
- Docker and Docker Compose
|
||||
- Git
|
||||
- Access to deployment server (for production/dev deployments)
|
||||
Documentation for the framework can be found on the [Laravel website](http://laravel.com/docs).
|
||||
|
||||
## 🛠️ Local Development
|
||||
## Contributing
|
||||
|
||||
### Building the Docker Image
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](http://laravel.com/docs/contributions).
|
||||
|
||||
```bash
|
||||
docker build -t merchbay:dev .
|
||||
```
|
||||
### License
|
||||
|
||||
### Running Locally
|
||||
|
||||
```bash
|
||||
# Create .env file from example
|
||||
cp .env.example .env
|
||||
|
||||
# Update .env with your local configuration
|
||||
# Set database credentials, mail settings, etc.
|
||||
|
||||
# Run with docker-compose (customize docker-compose.yml for local setup)
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
The following environment variables are required:
|
||||
|
||||
#### Database Configuration
|
||||
- `DB_HOST` - Database host
|
||||
- `DB_PORT` - Database port (default: 3306)
|
||||
- `DB_DATABASE` - Database name
|
||||
- `DB_USERNAME` - Database username
|
||||
- `DB_PASSWORD` - Database password
|
||||
|
||||
#### Application URLs
|
||||
- `APP_URL` - Application base URL
|
||||
- `PROD_PRIVATE` - Production private server URL
|
||||
- `IMAGES_URL` - Images server URL
|
||||
- `UPLOAD_URL` - Upload directory URL
|
||||
|
||||
#### Mail Configuration
|
||||
- `MAIL_DRIVER` - Mail driver (smtp)
|
||||
- `MAIL_HOST` - SMTP host
|
||||
- `MAIL_PORT` - SMTP port
|
||||
- `MAIL_USERNAME` - SMTP username
|
||||
- `MAIL_PASSWORD` - SMTP password
|
||||
- `MAIL_ENCRYPTION` - Encryption type (tls/ssl)
|
||||
|
||||
#### Third-Party Services
|
||||
- `CAPTCHA_SITE_KEY` - reCAPTCHA site key
|
||||
- `CAPTCHA_SECRET_KEY` - reCAPTCHA secret key
|
||||
- `ANALYTICS_SITE_ID` - Google Analytics site ID
|
||||
- `ANALYTICS_CLIENT_ID` - Google Analytics client ID
|
||||
- `ANALYTICS_SERVICE_EMAIL` - Google Analytics service email
|
||||
|
||||
## 🚢 Deployment
|
||||
|
||||
### Automated CI/CD with Gitea Actions
|
||||
|
||||
This project includes automated deployment workflows using Gitea Actions:
|
||||
|
||||
#### Development Deployment
|
||||
Push to the `dev` branch to automatically deploy to dev environment:
|
||||
```bash
|
||||
git push origin dev
|
||||
```
|
||||
- Deploys to: `https://dev.merchbay.app`
|
||||
|
||||
#### Production Deployment
|
||||
Push to the `main` or `master` branch to automatically deploy to production:
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
- Deploys to: `https://merchbay.app`
|
||||
|
||||
#### Docker Registry
|
||||
Create version tags to build and push to Docker registry:
|
||||
```bash
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
### Workflow Files
|
||||
|
||||
- `.gitea/workflows/deploy-dev.yml` - Development deployment
|
||||
- `.gitea/workflows/deploy.yml` - Production deployment
|
||||
- `.gitea/workflows/build-push.yml` - Docker image build and push
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
merchbay/
|
||||
├── app/ # Application core
|
||||
│ ├── Http/ # Controllers, middleware, routes
|
||||
│ ├── Models/ # Database models
|
||||
│ └── Services/ # Business logic services
|
||||
├── config/ # Configuration files
|
||||
├── database/ # Migrations and seeds
|
||||
├── public/ # Public assets (images, CSS, JS)
|
||||
├── resources/ # Views and frontend assets
|
||||
├── storage/ # Application storage
|
||||
├── docker-compose.yml # Docker compose configuration
|
||||
├── Dockerfile # Docker image definition
|
||||
└── docker-entrypoint.sh # Container startup script
|
||||
```
|
||||
|
||||
## 🔧 Development Notes
|
||||
|
||||
### Storage Permissions
|
||||
|
||||
The Docker entrypoint automatically creates and sets proper permissions for:
|
||||
- `storage/framework/views`
|
||||
- `storage/framework/cache`
|
||||
- `storage/framework/sessions`
|
||||
- `storage/logs`
|
||||
- `bootstrap/cache`
|
||||
|
||||
### PHP Extensions
|
||||
|
||||
The following PHP extensions are installed:
|
||||
- pdo_mysql
|
||||
- mbstring
|
||||
- exif
|
||||
- pcntl
|
||||
- bcmath
|
||||
- mcrypt (native in PHP 7.0)
|
||||
- tokenizer
|
||||
- zip
|
||||
- gd (with freetype and jpeg support)
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### 500 Internal Server Error
|
||||
|
||||
1. Check container logs: `docker logs merchbay_app`
|
||||
2. Verify storage permissions are set correctly
|
||||
3. Ensure all environment variables are configured in `.env`
|
||||
4. Check database connectivity
|
||||
|
||||
### Storage Permission Issues
|
||||
|
||||
The entrypoint script automatically fixes permissions on container start. If issues persist:
|
||||
```bash
|
||||
docker exec merchbay_app chown -R www-data:www-data storage bootstrap/cache
|
||||
docker exec merchbay_app chmod -R 775 storage bootstrap/cache
|
||||
```
|
||||
|
||||
## 📄 License
|
||||
|
||||
Proprietary - All rights reserved
|
||||
|
||||
## 🤝 Support
|
||||
|
||||
For support and questions, contact the development team.
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
||||
|
||||
106
rebuild.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if docker compose (new) or docker-compose (old) is available
|
||||
if command -v docker &>/dev/null; then
|
||||
if docker compose version &>/dev/null; then
|
||||
DOCKER_COMPOSE="docker compose"
|
||||
elif command -v docker-compose &>/dev/null; then
|
||||
DOCKER_COMPOSE="docker-compose"
|
||||
else
|
||||
echo "❌ Error: Neither 'docker compose' nor 'docker-compose' found."
|
||||
echo "Please install Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "❌ Error: Docker is not installed."
|
||||
echo "Please install Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🚀 Starting rebuild process..."
|
||||
|
||||
# Function to display usage
|
||||
show_usage() {
|
||||
echo "Usage: ./rebuild.sh [OPTIONS]"
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " -c, --clean Perform a clean rebuild (no cache)"
|
||||
echo " -f, --fresh Perform a fresh migration"
|
||||
}
|
||||
|
||||
# Default values
|
||||
CLEAN_BUILD=false
|
||||
FRESH_MIGRATION=false
|
||||
|
||||
# Parse arguments
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help) show_usage; exit 0 ;;
|
||||
-c|--clean) CLEAN_BUILD=true ;;
|
||||
-f|--fresh) FRESH_MIGRATION=true ;;
|
||||
*) echo "Unknown parameter: $1"; show_usage; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Pull latest changes from git
|
||||
echo "📥 Pulling latest changes from git..."
|
||||
if ! git pull; then
|
||||
echo "❌ Git pull failed. Please resolve any conflicts and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stop running containers
|
||||
echo "📥 Stopping running containers..."
|
||||
$DOCKER_COMPOSE down
|
||||
|
||||
# Remove old images if clean build
|
||||
if [ "$CLEAN_BUILD" = true ] ; then
|
||||
echo "🧹 Cleaning Docker cache..."
|
||||
$DOCKER_COMPOSE rm -f
|
||||
docker system prune -f
|
||||
fi
|
||||
|
||||
# Build and start containers
|
||||
echo "🏗️ Building containers..."
|
||||
if [ "$CLEAN_BUILD" = true ] ; then
|
||||
$DOCKER_COMPOSE build --no-cache
|
||||
else
|
||||
$DOCKER_COMPOSE build
|
||||
fi
|
||||
|
||||
# Start containers
|
||||
echo "🚀 Starting containers..."
|
||||
$DOCKER_COMPOSE up -d
|
||||
|
||||
# Wait for the containers to be ready
|
||||
echo "⏳ Waiting for containers to be ready..."
|
||||
sleep 10
|
||||
|
||||
# Clear Laravel cache
|
||||
echo "🧹 Clearing Laravel cache..."
|
||||
$DOCKER_COMPOSE exec app php artisan cache:clear
|
||||
$DOCKER_COMPOSE exec app php artisan config:clear
|
||||
$DOCKER_COMPOSE exec app php artisan view:clear
|
||||
|
||||
# Run composer install
|
||||
echo "📦 Installing dependencies..."
|
||||
$DOCKER_COMPOSE exec app composer install
|
||||
|
||||
# Generate application key if .env exists and APP_KEY is empty
|
||||
if [ -f .env ] && ! grep -q "^APP_KEY=[A-Za-z0-9+/]\{40\}$" .env; then
|
||||
echo "🔑 Generating application key..."
|
||||
$DOCKER_COMPOSE exec app php artisan key:generate
|
||||
fi
|
||||
|
||||
# Run migrations if requested
|
||||
if [ "$FRESH_MIGRATION" = true ] ; then
|
||||
echo "🔄 Running fresh migrations..."
|
||||
$DOCKER_COMPOSE exec app php artisan migrate:fresh
|
||||
else
|
||||
echo "🔄 Running migrations..."
|
||||
$DOCKER_COMPOSE exec app php artisan migrate
|
||||
fi
|
||||
|
||||
echo "✨ Rebuild completed!"
|
||||
echo "🌐 Your application should be available at http://localhost:8080"
|
||||
0
resources/views/designer/vue_designer.blade.php
Executable file → Normal file
0
resources/views/emails/contact_us.blade.php
Executable file → Normal file
@@ -540,13 +540,6 @@
|
||||
<td><b>Price</b></td>
|
||||
<td><b>Quantity</b></td>
|
||||
</tr>
|
||||
@elseif($item->FormUsed == 'number-size-form')
|
||||
<tr>
|
||||
<td><b>Number</b></td>
|
||||
<td><b>Size</b></td>
|
||||
<td><b>Price</b></td>
|
||||
<td><b>Quantity</b></td>
|
||||
</tr>
|
||||
@else
|
||||
@endif
|
||||
<!-- table header -->
|
||||
@@ -673,17 +666,6 @@
|
||||
<td>{{ $sub_item->Quantity }}
|
||||
</td>
|
||||
</tr>
|
||||
@elseif($item->FormUsed == 'number-size-form')
|
||||
<tr>
|
||||
<td>{{ $sub_item->Number }}
|
||||
</td>
|
||||
<td>{{ $sub_item->Size }}
|
||||
</td>
|
||||
<td>{{ $sub_item->Price }}
|
||||
</td>
|
||||
<td>{{ $sub_item->Quantity }}
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
@endif
|
||||
@endif
|
||||
|
||||
0
resources/views/errors/404.blade.php
Executable file → Normal file
@@ -174,15 +174,6 @@
|
||||
<th>Quantity</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@elseif($item->FormUsed == 'number-size-form')
|
||||
<tr>
|
||||
<th>Number</th>
|
||||
<th>Size</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
@else
|
||||
@endif
|
||||
|
||||
@@ -305,17 +296,6 @@
|
||||
href="{{ url('removeitem') }}/{{ $sub_item->Id }}"><i
|
||||
class="fa fa-times"></i></a></td>
|
||||
</tr>
|
||||
@elseif($item->FormUsed == 'number-size-form')
|
||||
<tr>
|
||||
<td>{{ $sub_item->Number }}</td>
|
||||
<td>{{ $sub_item->Size }}</td>
|
||||
<td>{{ $sub_item->Price . ' ' . $store_array[0]->StoreCurrency }}
|
||||
</td>
|
||||
<td>{{ $sub_item->Quantity }}</td>
|
||||
<td><a class="btn btn-xs btn-link pull-right"
|
||||
href="{{ url('removeitem') }}/{{ $sub_item->Id }}"><i
|
||||
class="fa fa-times"></i></a></td>
|
||||
</tr>
|
||||
@else
|
||||
@endif
|
||||
@endif
|
||||
|
||||
0
resources/views/merchbay/not_found.blade.php
Executable file → Normal file
0
resources/views/merchbay/privacy_policy.blade.php
Executable file → Normal file
0
resources/views/merchbay/terms_of_use.blade.php
Executable file → Normal file
0
resources/views/merchbay/track_order.blade.php
Executable file → Normal file
@@ -10,13 +10,13 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
|
||||
<title>Merchbay</title>
|
||||
<link rel="icon" href="{{ asset('/favicon.ico') }}">
|
||||
<link rel="icon" href="{{ asset('favicon.ico') }}">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
|
||||
<link href="{{ asset('/assets/css/merchbay/styles.css') }}" rel="stylesheet">
|
||||
<!-- <link href="{{ asset('/assets/login/css/style.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('/assets/login/css/form-elements.css') }}" rel="stylesheet"> -->
|
||||
<link href="{{ asset('assets/css/merchbay/styles.css') }}" rel="stylesheet">
|
||||
<!-- <link href="{{ asset('public/assets/login/css/style.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('public/assets/login/css/form-elements.css') }}" rel="stylesheet"> -->
|
||||
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-SB3QK6BR1N"></script>
|
||||
@@ -258,7 +258,7 @@
|
||||
}
|
||||
|
||||
function fetchCanada() {
|
||||
$.getJSON("{{ asset('//api/canada.json') }}", function(items) {
|
||||
$.getJSON("{{ asset('/api/canada.json') }}", function(items) {
|
||||
var states = [];
|
||||
|
||||
Object.keys(items).forEach(function(state) {
|
||||
@@ -307,7 +307,7 @@
|
||||
}
|
||||
|
||||
function fetchUSA() {
|
||||
$.getJSON("{{ asset('//api/usaCities.json') }}", function(data) {
|
||||
$.getJSON("{{ asset('/api/usaCities.json') }}", function(data) {
|
||||
var states = [];
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
|
||||
0
resources/views/paypal/payment_success.blade.php
Executable file → Normal file
@@ -1,45 +0,0 @@
|
||||
|
||||
<div class="panel-design-details" id="orderListPanel">
|
||||
<table class="table" id="tableRow" style="font-size:12px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<!-- <th>#</th> -->
|
||||
{{-- <th class="col-md-5">Name</th> --}}
|
||||
<th class="col-md-6">Number</th>
|
||||
<th class="col-md-5">Size</th>
|
||||
<th class="text-center"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="orderTableBody">
|
||||
<tr class="table-tr-0">
|
||||
{{-- <td>
|
||||
<input type="text" name="order_names[]" id="order_names" class="form-control input-sm inputName roster-input" placeholder="Name">
|
||||
</td> --}}
|
||||
<td>
|
||||
<select class="form-control input-sm roster-input" name="order_number[]">
|
||||
<option value="none">none</option>
|
||||
@for($i = 0; $i <= 99; $i++)
|
||||
<option value="{{ $i }}">{{ $i }}</option>
|
||||
@endfor
|
||||
<option value="00">00</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control input-sm order-size roster-input" name="order_size[]" style="border-right: 1px solid #ccc;" data-row-number="1">
|
||||
@foreach($sizes_array as $size)
|
||||
<option value="{{ $size->Size }}">{{ $size->SizeDisplay }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
<td id="action-column" class="text-center" style="padding: 4px !important; border-top: none">
|
||||
<span class="tr-remove-btn">
|
||||
<button type="button" id="addNewRow" class="btn btn-success btn-sm btn-roster-action" data-toggle="tooltip" title="Add Another"><i class="fa fa-plus" aria-hidden="true"></i></button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="addnew-btn-tbl-row">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
0
resources/views/teamstore-sublayouts/forms/roster-name-number-size-form.blade.php
Executable file → Normal file
@@ -7,12 +7,11 @@
|
||||
margin-top:20px;
|
||||
}
|
||||
</style>
|
||||
<div class="content-wrapper" id="addItem" style="min-height: 916px;">
|
||||
<div class="content-wrapper" style="min-height: 916px;">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Add Store Item
|
||||
{{-- <p>@{{ message }}</p> --}}
|
||||
Add Store Item
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url('user') }}"><i class="fa fa-home"></i> Home</a></li>
|
||||
@@ -93,9 +92,6 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Form</label>
|
||||
<div class="row">
|
||||
<div class="col-lg-10"></div>
|
||||
</div>
|
||||
<select class="form-control" name="itemForm">
|
||||
<option value="jersey-and-shorts-form">Jersey and Shorts Form</option>
|
||||
<option value="tshirt-form">T-Shirt Form</option>
|
||||
@@ -106,7 +102,6 @@
|
||||
<option value="name-size-form">Name and Size Form</option>
|
||||
<option value="jersey-and-shorts-quantity-form">Jersey, Shorts and Quantity Form</option>
|
||||
<option value="number-jersey-shorts-form">Number, Jersey and Shorts Form</option>
|
||||
<option value="number-size-form">Number and Size Form</option>
|
||||
<option value="roster-name-number-size-form">Roster and Size Form</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -125,8 +125,7 @@
|
||||
<option value="tshirt-form">T-Shirt Form</option>
|
||||
<option value="quantity-form">Quantity Form</option>
|
||||
<option value="name-and-number-form">Name and Number Form</option>
|
||||
<option value="name-and-number-form">Name and Number Form</option>
|
||||
<option value="number-size-form">Number and Size Form</option>
|
||||
<option value="name-number-size-form">Name, Number and Size Form</option>
|
||||
<option value="number-form">Number Only Form</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -86,6 +86,54 @@
|
||||
</div>
|
||||
<!-- ./col -->
|
||||
</div>
|
||||
{{-- <div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Total Sales</h3>
|
||||
<div class="box-tools">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="well">
|
||||
<div class="form-group col-md-3">
|
||||
<label class="control-label">Select Year: <span class="required">*</span></label>
|
||||
<select type="text" class="form-control" placeholder="Select Select Year">
|
||||
<option value="2020">2020</option>
|
||||
<option value="2019">2019</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label class="control-label">Select Month <span class="required">*</span></label>
|
||||
<select class="form-control" placeholder="Select Date">
|
||||
<option value="">January</option>
|
||||
<option value="">February</option>
|
||||
<option value="">March</option>
|
||||
<option value="">April</option>
|
||||
<option value="">May</option>
|
||||
<option value="">June</option>
|
||||
<option value="">July</option>
|
||||
<option value="">August</option>
|
||||
<option value="">September</option>
|
||||
<option value="">October</option>
|
||||
<option value="">November</option>
|
||||
<option value="">December</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="chart">
|
||||
<canvas id="myChart" style="height:350px"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
@else
|
||||
<div class="text-center" id="homepage-logo">
|
||||
|
||||
@@ -114,13 +114,6 @@
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
</tr>
|
||||
@elseif($array_item[0]->FormUsed=="number-size-form")
|
||||
<tr>
|
||||
<th>Number</th>
|
||||
<th>Size</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
</tr>
|
||||
@else
|
||||
|
||||
@endif
|
||||
@@ -202,13 +195,6 @@
|
||||
<td>{{ $array_item[0]->Price . ' ' . $store_array[0]->StoreCurrency }}</td>
|
||||
<td>{{ $array_item[0]->Quantity }}</td>
|
||||
</tr>
|
||||
@elseif($array_item[0]->FormUsed=="number-size-form")
|
||||
<tr>
|
||||
<td>{{ $array_item[0]->Number }}</td>
|
||||
<td>{{ $array_item[0]->Size }}</td>
|
||||
<td>{{ $array_item[0]->Price . ' ' . $store_array[0]->StoreCurrency }}</td>
|
||||
<td>{{ $array_item[0]->Quantity }}</td>
|
||||
</tr>
|
||||
@else
|
||||
|
||||
@endif
|
||||
|
||||
@@ -158,14 +158,6 @@
|
||||
<th>Quantity</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@elseif($item->FormUsed=="number-size-form")
|
||||
<tr>
|
||||
<th>Number</th>
|
||||
<th>Size</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@else
|
||||
|
||||
@endif
|
||||
@@ -227,13 +219,6 @@
|
||||
<td>{{ $sub_item->Price . ' ' . $array_payment_details[0]->Currency }}</td>
|
||||
<td>{{ $sub_item->Quantity }}</td>
|
||||
</tr>
|
||||
@elseif($item->FormUsed=="number-size-form")
|
||||
<tr>
|
||||
<td>{{ $sub_item->Number }}</td>
|
||||
<td>{{ $sub_item->Size }}</td>
|
||||
<td>{{ $sub_item->Price . ' ' . $array_payment_details[0]->Currency }}</td>
|
||||
<td>{{ $sub_item->Quantity }}</td>
|
||||
</tr>
|
||||
@else
|
||||
|
||||
@endif
|
||||
|
||||
@@ -127,7 +127,6 @@
|
||||
<option value="name-and-number-form">Name and Number Form</option>
|
||||
<option value="name-number-size-form">Name, Number and Size Form</option>
|
||||
<option value="number-form">Number Only Form</option>
|
||||
<option value="number-size-eform">Number and Size Form</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -13,41 +13,37 @@
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<!-- Bootstrap 3.3.6 -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/bootstrap/css/bootstrap.min.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/bootstrap/css/bootstrap.min.css')}}">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
|
||||
<!-- Ionicons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/dist/css/AdminLTE.min.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/dist/css/AdminLTE.min.css')}}">
|
||||
<!-- AdminLTE Skins. Choose a skin from the css/skins
|
||||
folder instead of downloading all of them to reduce the load. -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/dist/css/skins/_all-skins.min.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/dist/css/skins/_all-skins.min.css')}}">
|
||||
<!-- iCheck -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/plugins/iCheck/flat/blue.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/plugins/iCheck/flat/blue.css')}}">
|
||||
<!-- Date Picker -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/plugins/datepicker/datepicker3.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/plugins/datepicker/datepicker3.css')}}">
|
||||
<!-- Daterange picker -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/plugins/daterangepicker/daterangepicker.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/plugins/daterangepicker/daterangepicker.css')}}">
|
||||
<!-- bootstrap wysihtml5 - text editor -->
|
||||
<link rel="stylesheet" href="{{asset('/bower_components/AdminLTE/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css')}}">
|
||||
<link rel="stylesheet" href="{{asset('/public/bower_components/AdminLTE/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css')}}">
|
||||
<!-- Select2 -->
|
||||
<link href="{{asset('/bower_components/AdminLTE/plugins/select2/select2.min.css')}}" rel="stylesheet" />
|
||||
<link href="{{asset('/public/bower_components/AdminLTE/plugins/select2/select2.min.css')}}" rel="stylesheet" />
|
||||
<!-- ekko-lightbox -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.css" rel="stylesheet">
|
||||
<!-- bootstrap-toggle -->
|
||||
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
|
||||
<!-- DataTables -->
|
||||
<link rel="stylesheet" href="{{ asset('/bower_components/AdminLTE/plugins/datatables.net-bs/css/dataTables.bootstrap.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('/public/bower_components/AdminLTE/plugins/datatables.net-bs/css/dataTables.bootstrap.min.css') }}">
|
||||
<!-- datepicker -->
|
||||
<link rel="stylesheet" href="{{ asset('/bower_components/AdminLTE/plugins/datepicker/datepicker3.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('/public/bower_components/AdminLTE/plugins/datepicker/datepicker3.css') }}">
|
||||
<!-- jquery-ui -->
|
||||
<link href="{{ asset('/assets/css/jquery-ui.css') }}" rel="stylesheet">
|
||||
<link href="{{asset('/designer/css/build.css')}}" rel="stylesheet">
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<link href="{{ asset('/public/assets/css/jquery-ui.css') }}" rel="stylesheet">
|
||||
<link href="{{asset('/public/designer/css/build.css')}}" rel="stylesheet">
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
@@ -628,41 +624,41 @@
|
||||
<!-- ./wrapper -->
|
||||
|
||||
<!-- jQuery 2.2.3 -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/jQuery/jquery-2.2.3.min.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/jQuery/jquery-2.2.3.min.js')}}"></script>
|
||||
<!-- Bootstrap 3.3.6 -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/bootstrap/js/bootstrap.min.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/bootstrap/js/bootstrap.min.js')}}"></script>
|
||||
|
||||
<!-- daterangepicker -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.min.js"></script>
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/daterangepicker/daterangepicker.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/daterangepicker/daterangepicker.js')}}"></script>
|
||||
<!-- datepicker -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/datepicker/bootstrap-datepicker.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/datepicker/bootstrap-datepicker.js')}}"></script>
|
||||
<!-- Bootstrap WYSIHTML5 -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js')}}"></script>
|
||||
<!-- Slimscroll -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/slimScroll/jquery.slimscroll.min.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/slimScroll/jquery.slimscroll.min.js')}}"></script>
|
||||
<!-- FastClick -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/fastclick/fastclick.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/fastclick/fastclick.js')}}"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/dist/js/app.min.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/dist/js/app.min.js')}}"></script>
|
||||
<!-- AdminLTE dashboard demo (This is only for demo purposes)
|
||||
<script src="{{asset('/bower_components/AdminLTE/dist/js/pages/dashboard.js')}}"></script>-->
|
||||
<!-- AdminLTE for demo purposes -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/dist/js/demo.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/dist/js/demo.js')}}"></script>
|
||||
|
||||
<!-- Select2 -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
|
||||
<!-- validate jquery -->
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
|
||||
<!-- \priceformat -->
|
||||
<script src="{{asset('/designer/js/jquery.priceformat.min.js')}}"></script>
|
||||
<script src="{{asset('/public/designer/js/jquery.priceformat.min.js')}}"></script>
|
||||
<!-- ekko-lightbox -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.js"></script>
|
||||
<!-- bootstrap-toggle -->
|
||||
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
|
||||
<!-- DataTables -->
|
||||
<script src="{{ asset('/bower_components/AdminLTE/plugins/datatables.net/js/jquery.dataTables.min.js') }}"></script>
|
||||
<script src="{{ asset('/bower_components/AdminLTE/plugins/datatables.net-bs/js/dataTables.bootstrap.min.js') }}"></script>
|
||||
<script src="{{ asset('/public/bower_components/AdminLTE/plugins/datatables.net/js/jquery.dataTables.min.js') }}"></script>
|
||||
<script src="{{ asset('/public/bower_components/AdminLTE/plugins/datatables.net-bs/js/dataTables.bootstrap.min.js') }}"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.flash.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
|
||||
@@ -671,9 +667,9 @@
|
||||
<script src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.html5.min.js"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.print.min.js"></script>
|
||||
<!-- datepicker -->
|
||||
<script src="{{asset('/bower_components/AdminLTE/plugins/datepicker/bootstrap-datepicker.js')}}"></script>
|
||||
<script src="{{asset('/public/bower_components/AdminLTE/plugins/datepicker/bootstrap-datepicker.js')}}"></script>
|
||||
<!-- jquery-ui -->
|
||||
<script src="{{ asset('/assets/js/jquery-ui.js') }}"></script>
|
||||
<script src="{{ asset('/public/assets/js/jquery-ui.js') }}"></script>
|
||||
{{-- Chartjs --}}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
|
||||
|
||||
@@ -1791,7 +1787,7 @@
|
||||
}
|
||||
|
||||
function fetchCanada() {
|
||||
$.getJSON("{{ asset('/api/canada.json') }}", function(items) {
|
||||
$.getJSON("{{ asset('/public/api/canada.json') }}", function(items) {
|
||||
var states = [];
|
||||
|
||||
Object.keys(items).forEach(function(state) {
|
||||
@@ -1840,7 +1836,7 @@
|
||||
}
|
||||
|
||||
function fetchUSA() {
|
||||
$.getJSON("{{ asset('/api/usaCities.json') }}", function(data) {
|
||||
$.getJSON("{{ asset('/public/api/usaCities.json') }}", function(data) {
|
||||
var states = [];
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
@@ -2154,6 +2150,7 @@
|
||||
|
||||
function submitFormItemDetails() {
|
||||
var data = $("#frm-item-details").serialize();
|
||||
// console.log(data)
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: "{{ url('user/store-items/update') }}",
|
||||
|
||||
@@ -1,644 +1,277 @@
|
||||
@extends('user-layouts.user_template')
|
||||
@section('content')
|
||||
<style>
|
||||
.hide-bullets {
|
||||
list-style: none;
|
||||
margin-left: -40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="content-wrapper" id="viewStoreItem" style="min-height: 916px;">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@{{ title }}
|
||||
<small>{{ $product_array[0]->ProductName }}</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url('user') }}"><i class="fa fa-home"></i> Home</a></li>
|
||||
<li><a href="{{ url('user/store-items') }}"><i class="fa fa-th"></i> Store Items</a></li>
|
||||
<li class="active">{{ $product_array[0]->ProductName }}</li>
|
||||
</ol>
|
||||
</section>
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<button type="button" class="btn btn-default pull-right" data-toggle="modal"
|
||||
data-target="#myModal">Re-arrange / Delete thumbnail</button>
|
||||
<button type="button" class="btn btn-danger pull-right" id="btn_delete_store_id"
|
||||
style="margin-right: 5px;" data-id="{{ $product_array[0]->Id }}">Delete this
|
||||
Item</button>
|
||||
<style>
|
||||
.hide-bullets {
|
||||
list-style: none;
|
||||
margin-left: -40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
<div class="content-wrapper" style="min-height: 916px;">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Store Item
|
||||
<small>{{ $product_array[0]->ProductName }}</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url('user') }}"><i class="fa fa-home"></i> Home</a></li>
|
||||
<li><a href="{{ url('user/store-items') }}"><i class="fa fa-th"></i> Store Items</a></li>
|
||||
<li class="active">{{ $product_array[0]->ProductName }}</li>
|
||||
</ol>
|
||||
</section>
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<button type="button" class="btn btn-default pull-right" data-toggle="modal" data-target="#myModal">Re-arrange / Delete thumbnail</button>
|
||||
<button type="button" class="btn btn-danger pull-right" id="btn_delete_store_id" style="margin-right: 5px;" data-id="{{ $product_array[0]->Id }}">Delete this Item</button>
|
||||
</div>
|
||||
<div class="box-body custom-box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
@foreach($thumbnails_array as $thumbnail)
|
||||
@if($thumbnail->ImageClass == 'active')
|
||||
<img style="height:400px" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" id="main-thumbnail">
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul class="hide-bullets">
|
||||
<li class="col-sm-3 col-xs-4">
|
||||
<a class="thumbnail btn-add-thumbnail" style="border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; margin-bottom: -28px; cursor: pointer;">
|
||||
<!-- <span class="close">×</span> -->
|
||||
<img class="img img-responsive product-center " style="height: 65.45px;" src="{{ asset('/public/images/add-new-img.svg') }}" />
|
||||
<!-- <p class="center">Add Image</p> -->
|
||||
<p class="text-center">
|
||||
Add Image
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
@foreach($thumbnails_array as $thumbnail)
|
||||
<li class="col-sm-3 col-xs-4">
|
||||
<a class="thumbnail a_thumbnail {{ $thumbnail->ImageClass }}" style="border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; margin-bottom: -28px;">
|
||||
<!-- <span class="close">×</span> -->
|
||||
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" />
|
||||
</a>
|
||||
<div class="funkyradio">
|
||||
<div class="funkyradio-primary">
|
||||
<input type="radio" id="{{ 'radio-' .$thumbnail->Id }}" data-product-id="{{ $product_array[0]->Id }}" data-id="{{ $thumbnail->Id }}" name="setActive" @if($thumbnail->ImageClass != null) checked @endif />
|
||||
<label for="{{ 'radio-' .$thumbnail->Id }}" style="border-top-left-radius: 0px; border-top-right-radius: 0px;">active</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="col-md-5">
|
||||
asdasdadadsaad
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Item Details
|
||||
</h3>
|
||||
</div>
|
||||
<form id="frm-item-details">
|
||||
<!-- <input type="hidden" name="design_code" class="form-control" value=""> -->
|
||||
<div class="box-body custom-box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
@foreach ($thumbnails_array as $thumbnail)
|
||||
@if ($thumbnail->ImageClass == 'active')
|
||||
<img style="height:400px"
|
||||
src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}"
|
||||
id="main-thumbnail">
|
||||
@endif
|
||||
<input type="hidden" class="form-control" name="item_url" value="{{ $product_array[0]->ProductURL }}" placeholder="Item Name">
|
||||
<div class="form-group">
|
||||
<label>SKU</label>
|
||||
<input type="text" class="form-control" name="sku" value="{{ $product_array[0]->ProductCode }}" placeholder="SKU">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Name</label>
|
||||
<input type="text" class="form-control" name="itemName" value="{{ $product_array[0]->ProductName }}" placeholder="Item Name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Desription</label>
|
||||
<textarea class="form-control" name="itemDescription">{{ $product_array[0]->ProductDescription }}</textarea>
|
||||
</div>
|
||||
<!-- <div class="form-group">
|
||||
|
||||
<div class="checkbox checkbox-inline">
|
||||
<input type="checkbox" class="styled" id="sale_chk" name="sale_chk" checked >
|
||||
<label for="sale_chk"> Sell Item</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox checkbox-inline">
|
||||
<input type="checkbox" class="styled" id="publish_chk" name="publish_chk" >
|
||||
<label for="publish_chk"> Publish Design</label>
|
||||
</div>
|
||||
|
||||
</div> -->
|
||||
<div class="form-group">
|
||||
<label>Item Price</label>
|
||||
<input id="item_price" name="item_price" class="form-control price_format" type="text" value="{{ $product_array[0]->ProductPrice }}" data-error="#err-price" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Form</label>
|
||||
<select class="form-control" name="itemForm">
|
||||
<option value="jersey-and-shorts-form" @if($product_array[0]->ProductForm == "jersey-and-shorts-form") selected @endif>Jersey and Shorts Form</option>
|
||||
<option value="tshirt-form" @if($product_array[0]->ProductForm == "tshirt-form") selected @endif>T-Shirt Form</option>
|
||||
<option value="quantity-form" @if($product_array[0]->ProductForm == "quantity-form") selected @endif>Quantity Form</option>
|
||||
<option value="name-number-form" @if($product_array[0]->ProductForm == "name-number-form") selected @endif>Name and Number Form</option>
|
||||
<option value="name-number-size-form" @if($product_array[0]->ProductForm == "name-number-size-form") selected @endif>Name, Number and Size Form</option>
|
||||
<option value="number-form" @if($product_array[0]->ProductForm == "number-form") selected @endif>Number Only Form</option>
|
||||
<option value="name-size-form" @if($product_array[0]->ProductForm == "name-size-form") selected @endif>Name and Size Form</option>
|
||||
<option value="jersey-and-shorts-quantity-form" @if($product_array[0]->ProductForm == "jersey-and-shorts-quantity-form") selected @endif>Jersey, Shorts and Quantity Form</option>
|
||||
<option value="number-jersey-shorts-form" @if($product_array[0]->ProductForm == "number-jersey-shorts-form") selected @endif>Number, Jersey and Shorts Form</option>
|
||||
<option value="roster-name-number-size-form" @if($product_array[0]->ProductForm == "roster-name-number-size-form") selected @endif>Roster and Size Form</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Available Size</label>
|
||||
<select class="form-control select2" data-error="#err_available_size" data-placeholder="Select Size" name="available_size[]" multiple="multiple" required>
|
||||
<option value="toddler" @if(in_array("toddler", $available_size)) selected @endif>Toddler</option>
|
||||
<option value="youth" @if(in_array("youth", $available_size)) selected @endif>Youth</option>
|
||||
<option value="adult" @if(in_array("adult", $available_size)) selected @endif>Adult</option>
|
||||
<option value="mask" @if(in_array("mask", $available_size)) selected @endif>Mask</option>
|
||||
<option value="gaiter" @if(in_array("gaiter", $available_size)) selected @endif>Gaiter</option>
|
||||
<option value="buckethat" @if(in_array("buckethat", $available_size)) selected @endif>Buckethat</option>
|
||||
<option value="none" @if(in_array("none", $available_size)) selected @endif>None</option>
|
||||
</select>
|
||||
<span id="err_available_size"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Quantity <small>(Optional)</small></label>
|
||||
<input id="item_quantity" name="item_quantity" class="form-control" type="number" min="0" value="{{ $product_array[0]->ProductAvailableQty }}" data-error="#err-quantity" />
|
||||
</div>
|
||||
{{-- {{ var_dump($product_array[0]) }} --}}
|
||||
<div class="form-group">
|
||||
<label>Item Privacy</label>
|
||||
<select class="form-control" name="item_privacy">
|
||||
<option value="public" @if($product_array[0]->PrivacyStatus == "public") selected @endif>Public</option>
|
||||
<option value="private" @if($product_array[0]->PrivacyStatus == "private") selected @endif>Private</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Select Shipping Category</label>
|
||||
<select class="form-control" name="shipping_cost" required>
|
||||
<option value="0">None</option>
|
||||
@foreach ($shipping_cost as $sc)
|
||||
<option value="{{ $sc->Id }}" @if($sc->Id == $product_array[0]->ShippingCostId) selected @endif>{{ $sc->DisplayName }}</option>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul class="hide-bullets">
|
||||
<li class="col-sm-3 col-xs-4">
|
||||
<a class="thumbnail btn-add-thumbnail"
|
||||
style="border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; margin-bottom: -28px; cursor: pointer;">
|
||||
<!-- <span class="close">×</span> -->
|
||||
<img class="img img-responsive product-center "
|
||||
style="height: 65.45px;"
|
||||
src="{{ asset('/public/images/add-new-img.svg') }}" />
|
||||
<!-- <p class="center">Add Image</p> -->
|
||||
<p class="text-center">
|
||||
Add Image
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
@foreach ($thumbnails_array as $thumbnail)
|
||||
<li class="col-sm-3 col-xs-4">
|
||||
<a class="thumbnail a_thumbnail {{ $thumbnail->ImageClass }}"
|
||||
style="border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; margin-bottom: -28px;">
|
||||
<!-- <span class="close">×</span> -->
|
||||
<img class="img img-responsive product-center image-thumbnails"
|
||||
style="height: 59.45px;"
|
||||
src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" />
|
||||
</a>
|
||||
<div class="funkyradio">
|
||||
<div class="funkyradio-primary">
|
||||
<input type="radio" id="{{ 'radio-' . $thumbnail->Id }}"
|
||||
data-product-id="{{ $product_array[0]->Id }}"
|
||||
data-id="{{ $thumbnail->Id }}" name="setActive"
|
||||
@if ($thumbnail->ImageClass != null) checked @endif />
|
||||
<label for="{{ 'radio-' . $thumbnail->Id }}"
|
||||
style="border-top-left-radius: 0px; border-top-right-radius: 0px;">active</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="col-md-5">
|
||||
asdasdadadsaad
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Item Details
|
||||
</h3>
|
||||
</div>
|
||||
<form id="frm-item-details">
|
||||
<!-- <input type="hidden" name="design_code" class="form-control" value=""> -->
|
||||
<div class="box-body custom-box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<input type="hidden" class="form-control" name="item_url"
|
||||
value="{{ $product_array[0]->ProductURL }}" placeholder="Item Name">
|
||||
<div class="form-group">
|
||||
<label>SKU</label>
|
||||
<input type="text" class="form-control" name="sku"
|
||||
value="{{ $product_array[0]->ProductCode }}" placeholder="SKU">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Name</label>
|
||||
<input type="text" class="form-control" name="itemName"
|
||||
value="{{ $product_array[0]->ProductName }}" placeholder="Item Name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Desription</label>
|
||||
<textarea class="form-control" name="itemDescription">{{ $product_array[0]->ProductDescription }}</textarea>
|
||||
</div>
|
||||
<!-- <div class="form-group">
|
||||
|
||||
<div class="checkbox checkbox-inline">
|
||||
<input type="checkbox" class="styled" id="sale_chk" name="sale_chk" checked >
|
||||
<label for="sale_chk"> Sell Item</label>
|
||||
</div>
|
||||
|
||||
<div class="checkbox checkbox-inline">
|
||||
<input type="checkbox" class="styled" id="publish_chk" name="publish_chk" >
|
||||
<label for="publish_chk"> Publish Design</label>
|
||||
</div>
|
||||
|
||||
</div> -->
|
||||
<div class="form-group">
|
||||
<label>Item Price</label>
|
||||
<input id="item_price" name="item_price" class="form-control price_format"
|
||||
type="text" value="{{ $product_array[0]->ProductPrice }}"
|
||||
data-error="#err-price" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Form</label>
|
||||
<select class="form-control" name="itemForm" v-model="itemFormSelected"
|
||||
@change="handleSelectItemForm">
|
||||
<option value="jersey-and-shorts-form"
|
||||
@if ($product_array[0]->ProductForm == 'jersey-and-shorts-form') selected @endif>Jersey and Shorts
|
||||
Form</option>
|
||||
<option value="tshirt-form"
|
||||
@if ($product_array[0]->ProductForm == 'tshirt-form') selected @endif>T-Shirt Form
|
||||
</option>
|
||||
<option value="quantity-form"
|
||||
@if ($product_array[0]->ProductForm == 'quantity-form') selected @endif>Quantity Form
|
||||
</option>
|
||||
<option value="name-number-form"
|
||||
@if ($product_array[0]->ProductForm == 'name-number-form') selected @endif>Name and Number
|
||||
Form</option>
|
||||
<option value="name-number-size-form"
|
||||
@if ($product_array[0]->ProductForm == 'name-number-size-form') selected @endif>Name, Number and
|
||||
Size Form</option>
|
||||
<option value="number-size-form"
|
||||
@if ($product_array[0]->ProductForm == 'number-size-form') selected @endif>Number and Size
|
||||
Form</option>
|
||||
<option value="number-form"
|
||||
@if ($product_array[0]->ProductForm == 'number-form') selected @endif>Number Only Form
|
||||
</option>
|
||||
<option value="name-size-form"
|
||||
@if ($product_array[0]->ProductForm == 'name-size-form') selected @endif>Name and Size Form
|
||||
</option>
|
||||
<option value="jersey-and-shorts-quantity-form"
|
||||
@if ($product_array[0]->ProductForm == 'jersey-and-shorts-quantity-form') selected @endif>Jersey, Shorts
|
||||
and Quantity Form</option>
|
||||
<option value="number-jersey-shorts-form"
|
||||
@if ($product_array[0]->ProductForm == 'number-jersey-shorts-form') selected @endif>Number, Jersey
|
||||
and Shorts Form</option>
|
||||
<option value="roster-name-number-size-form"
|
||||
@if ($product_array[0]->ProductForm == 'roster-name-number-size-form') selected @endif>Roster and Size
|
||||
Form</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group d-flex"
|
||||
v-if="itemFormSelected == 'roster-name-number-size-form'">
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
@click="addRosterModal">
|
||||
<i class="fa fa-plus"></i> Add Roster
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning btn-sm"
|
||||
@click="viewRosterModal">
|
||||
<i class="fa fa-eye"></i> View Roster
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Available Size</label>
|
||||
<select class="form-control select2" data-error="#err_available_size"
|
||||
data-placeholder="Select Size" name="available_size[]"
|
||||
multiple="multiple" required>
|
||||
<option value="toddler"
|
||||
@if (in_array('toddler', $available_size)) selected @endif>Toddler</option>
|
||||
<option value="youth" @if (in_array('youth', $available_size)) selected @endif>
|
||||
Youth</option>
|
||||
<option value="adult" @if (in_array('adult', $available_size)) selected @endif>
|
||||
Adult</option>
|
||||
<option value="mask" @if (in_array('mask', $available_size)) selected @endif>
|
||||
Mask</option>
|
||||
<option value="gaiter" @if (in_array('gaiter', $available_size)) selected @endif>
|
||||
Gaiter</option>
|
||||
<option value="buckethat"
|
||||
@if (in_array('buckethat', $available_size)) selected @endif>Buckethat
|
||||
</option>
|
||||
<option value="none" @if (in_array('none', $available_size)) selected @endif>
|
||||
None</option>
|
||||
</select>
|
||||
<span id="err_available_size"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Item Quantity <small>(Optional)</small></label>
|
||||
<input id="item_quantity" name="item_quantity" class="form-control"
|
||||
type="number" min="0"
|
||||
value="{{ $product_array[0]->ProductAvailableQty }}"
|
||||
data-error="#err-quantity" />
|
||||
</div>
|
||||
{{-- {{ var_dump($product_array[0]) }} --}}
|
||||
<div class="form-group">
|
||||
<label>Item Privacy</label>
|
||||
<select class="form-control" name="item_privacy">
|
||||
<option value="public" @if ($product_array[0]->PrivacyStatus == 'public') selected @endif>
|
||||
Public</option>
|
||||
<option value="private"
|
||||
@if ($product_array[0]->PrivacyStatus == 'private') selected @endif>Private</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Select Shipping Category</label>
|
||||
<select class="form-control" name="shipping_cost" required>
|
||||
<option value="0">None</option>
|
||||
@foreach ($shipping_cost as $sc)
|
||||
<option value="{{ $sc->Id }}"
|
||||
@if ($sc->Id == $product_array[0]->ShippingCostId) selected @endif>
|
||||
{{ $sc->DisplayName }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span id="err_available_size"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<!-- <button type="submit" class="btn btn-default">Cancel</button> -->
|
||||
<button type="submit" class="btn btn-primary pull-right">Save changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Item Images</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Image</th>
|
||||
<th class="col-sm-2 text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sortable">
|
||||
@foreach ($thumbnails_array as $thumbnail)
|
||||
<tr id="{{ 'item-' . $thumbnail->Id }}">
|
||||
<td class="text-center" style="width: 50px"><i class="fa fa-bars"></i></td>
|
||||
<td><img class="img img-responsive product-center" style="height: 59.45px;"
|
||||
src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" />
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<!-- <button class="btn btn-default btn-xs btn-edit-clipart" data-id="#"><i class="fa fa-edit"></i></button> -->
|
||||
<button class="btn btn-default btn-sm btn-delete-item-image"
|
||||
data-id="{{ $thumbnail->Id }}" data-filename="{{ $thumbnail->Image }}"
|
||||
title="Delete Image"><i class="fa fa-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="btn_save_thumbnail_sorting">Save
|
||||
Changes</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" id="modal_add_thumbnail" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<form id="frm_add_new_images">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Add Image</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row grid-divider">
|
||||
<div class="col-sm-4">
|
||||
<div class="col-padding">
|
||||
<h3>Select Image(s)</h3>
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="_id" value="{{ $product_array[0]->Id }}" />
|
||||
<input type="file" class="form-control" id="upload_images"
|
||||
name="upload_images[]" multiple accept="image/*" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" id="clear_frm_add_new_images"
|
||||
class="btn btn-default btn-block">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="col-padding">
|
||||
<h3>Preview</h3>
|
||||
<div class="col-md-12">
|
||||
<ul class="hide-bullets small-preview-thumb">
|
||||
</ul>
|
||||
</div>
|
||||
</select>
|
||||
<span id="err_available_size"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" id="btn_submit_new_item_image" class="btn btn-primary">Submit</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<div class="box-footer">
|
||||
<!-- <button type="submit" class="btn btn-default">Cancel</button> -->
|
||||
<button type="submit" class="btn btn-primary pull-right">Save changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modalAddRoster" role="dialog" data-backdrop="static" data-keyboard="false">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
{{-- @{{ roster }} --}}
|
||||
<form @submit.prevent="onRosterSubmit">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Add Roster</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Number</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr v-for="(item, i) in roster" :key="i">
|
||||
<td style="padding: 0px 0px 0px 8px;">@{{ i + 1 }}</td>
|
||||
<td style="padding: 0px 0px 0px 8px;"><input type="text" placeholder="Player Name"
|
||||
v-model="roster[i]['Name']" class="form-control"></td>
|
||||
<td style="padding: 0px 8px 0px 0px;"><input type="text"
|
||||
placeholder="Player Number" v-model="roster[i]['Number']" maxlength="2"
|
||||
class="form-control"></td>
|
||||
<td style="padding: 0px 8px 0px 0px; text-align: end;">
|
||||
<button type="button" @click="removeRosterRow(i)" :disabled="roster.length <= 1"
|
||||
class="btn btn-danger"><i class="fa fa-times-circle-o"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" style="padding: 8px 8px 0px 8px; text-align: end;">
|
||||
<button type="button" @click="addRosterRow" class="btn btn-primary">Add
|
||||
Row</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" :disabled="isSubmit">
|
||||
<i v-if="isSubmit" class="fa fa-spinner fa-spin"></i> Submit
|
||||
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Item Images</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Image</th>
|
||||
<th class="col-sm-2 text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sortable">
|
||||
@foreach($thumbnails_array as $thumbnail)
|
||||
|
||||
<div class="modal fade" id="modalViewRoster" role="dialog" data-backdrop="static" data-keyboard="false">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form @submit.prevent="onRosterUpdate">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Roster</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div style="text-align: end;">
|
||||
<button type="button" @click.prevent="getRoster" class="btn btn-success" :disabled="isRefresh">
|
||||
<i v-if="isRefresh" class="fa fa-spinner fa-spin"></i> Refresh
|
||||
|
||||
</button>
|
||||
</div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Number</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr v-for="(item, i) in currentRoster" :key="i">
|
||||
<td style="padding: 0px 0px 0px 8px;">@{{ i + 1 }}</td>
|
||||
<td style="padding: 0px 0px 0px 8px;"><input type="text" placeholder="Player Name"
|
||||
v-model="currentRoster[i]['Name']" class="form-control"></td>
|
||||
<td style="padding: 0px 8px 0px 0px;"><input type="text" maxlength="2"
|
||||
placeholder="Player Number" v-model="currentRoster[i]['Number']"
|
||||
class="form-control"></td>
|
||||
<td style="padding: 0px 8px 0px 0px; text-align: end;">
|
||||
<button type="button" @click="deleteRoster(i, item)" class="btn btn-danger"><i
|
||||
class="fa fa-trash-o"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{{-- <tr>
|
||||
<td colspan="4" style="padding: 8px 8px 0px 8px; text-align: end;">
|
||||
<button type="button" @click="addRosterRow" class="btn btn-primary">Add
|
||||
Row</button>
|
||||
</td>
|
||||
</tr> --}}
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" :disabled="isSubmit">
|
||||
<i v-if="isSubmit" class="fa fa-spinner fa-spin"></i> Update
|
||||
<tr id="{{ 'item-' . $thumbnail->Id }}">
|
||||
<td class="text-center" style="width: 50px"><i class="fa fa-bars"></i></td>
|
||||
<td><img class="img img-responsive product-center" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" /></td>
|
||||
<td class="text-center">
|
||||
<!-- <button class="btn btn-default btn-xs btn-edit-clipart" data-id="#"><i class="fa fa-edit"></i></button> -->
|
||||
<button class="btn btn-default btn-sm btn-delete-item-image" data-id="{{ $thumbnail->Id }}" data-filename="{{ $thumbnail->Image }}" title="Delete Image"><i class="fa fa-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="btn_save_thumbnail_sorting">Save Changes</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#viewStoreItem',
|
||||
data: {
|
||||
title: "Store Item", // Passing Laravel data to Vue
|
||||
showAddRoster: false,
|
||||
itemFormSelected: {!! json_encode($product_array[0]->ProductForm) !!},
|
||||
roster: [{
|
||||
Name: "",
|
||||
Number: "",
|
||||
ProductId: {!! json_encode($product_array[0]->Id) !!}
|
||||
}],
|
||||
|
||||
currentRoster: {!! json_encode($roster) !!},
|
||||
toBeDeletedRoster: [],
|
||||
isSubmit: false,
|
||||
isRefresh: false
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleSelectItemForm() {
|
||||
console.log('Selected option:', this.itemFormSelected);
|
||||
},
|
||||
|
||||
addRosterRow() {
|
||||
this.roster.push({
|
||||
Name: "",
|
||||
Number: "",
|
||||
ProductId: {!! json_encode($product_array[0]->Id) !!}
|
||||
})
|
||||
},
|
||||
|
||||
deleteRoster(i, item) {
|
||||
this.currentRoster.splice(i, 1);
|
||||
this.toBeDeletedRoster.push(item.Id);
|
||||
},
|
||||
|
||||
async onRosterUpdate() {
|
||||
// this.isSubmit = true;
|
||||
|
||||
if (this.toBeDeletedRoster.length > 0) {
|
||||
this.postDeleteRoster();
|
||||
}
|
||||
|
||||
await this.updateRoster();
|
||||
|
||||
// this.isSubmit = false;
|
||||
},
|
||||
|
||||
async postDeleteRoster() {
|
||||
|
||||
const token = $('meta[name="csrf_token"]').attr('content')
|
||||
axios.post("{{ url('user/roster-delete') }}", {
|
||||
data: this.toBeDeletedRoster
|
||||
}, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'X-CSRF-TOKEN': token
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.isSubmit = false;
|
||||
console.log(response.data);
|
||||
// alert("Roster is successfully saved.");
|
||||
// $('#modalAddRoster').modal('hide');
|
||||
// this.roster = [{
|
||||
// Name: "",
|
||||
// Number: "",
|
||||
// ProductId: {!! json_encode($product_array[0]->Id) !!}
|
||||
// }]
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error); // Handle error
|
||||
this.isSubmit = false; // Hide loading indicator
|
||||
});
|
||||
},
|
||||
|
||||
async onRosterSubmit() {
|
||||
this.isSubmit = true;
|
||||
const token = $('meta[name="csrf_token"]').attr('content')
|
||||
axios.post("{{ url('user/roster') }}", {
|
||||
data: this.roster
|
||||
}, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'X-CSRF-TOKEN': token
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.isSubmit = false;
|
||||
console.log(response.data);
|
||||
|
||||
const res = response.data;
|
||||
|
||||
if (!res.status) {
|
||||
alert(res.message);
|
||||
return
|
||||
}
|
||||
|
||||
alert(res.message);
|
||||
$('#modalAddRoster').modal('hide');
|
||||
this.roster = [{
|
||||
Name: "",
|
||||
Number: "",
|
||||
ProductId: {!! json_encode($product_array[0]->Id) !!}
|
||||
}]
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error); // Handle error
|
||||
this.isSubmit = false; // Hide loading indicator
|
||||
});
|
||||
},
|
||||
|
||||
async updateRoster() {
|
||||
this.isSubmit = true;
|
||||
const token = $('meta[name="csrf_token"]').attr('content')
|
||||
axios.post("{{ url('user/roster-update') }}", {
|
||||
data: this.currentRoster
|
||||
}, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'X-CSRF-TOKEN': token
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.isSubmit = false;
|
||||
console.log(response.data);
|
||||
alert("Roster is successfully updated.");
|
||||
$('#modalViewRoster').modal('hide');
|
||||
<div class="modal fade" id="modal_add_thumbnail" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<form id="frm_add_new_images">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Add Image</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row grid-divider">
|
||||
<div class="col-sm-4">
|
||||
<div class="col-padding">
|
||||
<h3>Select Image(s)</h3>
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="_id" value="{{ $product_array[0]->Id }}" />
|
||||
<input type="file" class="form-control" id="upload_images" name="upload_images[]" multiple accept="image/*" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" id="clear_frm_add_new_images" class="btn btn-default btn-block">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="col-padding">
|
||||
<h3>Preview</h3>
|
||||
<div class="col-md-12">
|
||||
<ul class="hide-bullets small-preview-thumb">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" id="btn_submit_new_item_image" class="btn btn-primary">Submit</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error); // Handle error
|
||||
this.isSubmit = false; // Hide loading indicator
|
||||
});
|
||||
},
|
||||
|
||||
async getRoster() {
|
||||
this.isRefresh = true;
|
||||
const productId = {!! json_encode($product_array[0]->Id) !!}
|
||||
const token = $('meta[name="csrf_token"]').attr('content')
|
||||
axios.get("{{ url('user/roster') }}", {
|
||||
params: {
|
||||
'product-id': productId
|
||||
}
|
||||
}, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'X-CSRF-TOKEN': token
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.isRefresh = false;
|
||||
console.log("getRoster", response)
|
||||
this.currentRoster = response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error); // Handle error
|
||||
this.isRefresh = false;
|
||||
});
|
||||
},
|
||||
|
||||
removeRosterRow(i) {
|
||||
this.roster.splice(i, 1);
|
||||
},
|
||||
|
||||
addRosterModal() {
|
||||
$('#modalAddRoster').modal('show');
|
||||
},
|
||||
|
||||
viewRosterModal() {
|
||||
$('#modalViewRoster').modal('show');
|
||||
// this.getRoster()
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
66
start-local.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Quick start script for local development and testing before Cloud Run deployment
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting Merchbay Laravel Application Setup..."
|
||||
|
||||
# Check if Docker is running
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "❌ Docker is not running. Please start Docker and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine which docker compose command to use
|
||||
if command -v docker-compose > /dev/null 2>&1; then
|
||||
DOCKER_COMPOSE="docker-compose"
|
||||
elif docker compose version > /dev/null 2>&1; then
|
||||
DOCKER_COMPOSE="docker compose"
|
||||
else
|
||||
echo "❌ Neither 'docker-compose' nor 'docker compose' is available."
|
||||
echo "Please install Docker Compose and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "ℹ️ Using: $DOCKER_COMPOSE"
|
||||
|
||||
# Check if .env file exists
|
||||
if [ ! -f .env ]; then
|
||||
echo "📄 Creating .env file from .env.example..."
|
||||
cp .env.example .env
|
||||
echo "✅ .env file created. Please update it with your configuration."
|
||||
fi
|
||||
|
||||
# Build and start services
|
||||
echo "🔨 Building Docker images..."
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml build
|
||||
|
||||
echo "🚀 Starting services..."
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml up -d
|
||||
|
||||
echo "⏳ Waiting for services to be ready..."
|
||||
sleep 30
|
||||
|
||||
# Run Laravel setup commands
|
||||
echo "🔧 Setting up Laravel..."
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan key:generate
|
||||
#$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan migrate --force
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan config:cache
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan route:cache
|
||||
$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan view:cache
|
||||
|
||||
echo "✅ Setup complete!"
|
||||
echo ""
|
||||
echo "🌐 Your application is now running at:"
|
||||
echo " Application: http://localhost:8080"
|
||||
echo " phpMyAdmin: http://localhost:8081"
|
||||
echo ""
|
||||
echo "📊 Check logs with:"
|
||||
echo " $DOCKER_COMPOSE -f docker-compose.local.yml logs -f app"
|
||||
echo ""
|
||||
echo "🛑 Stop the application with:"
|
||||
echo " $DOCKER_COMPOSE -f docker-compose.local.yml down"
|
||||
echo ""
|
||||
echo "🚀 When ready to deploy to Cloud Run, use:"
|
||||
echo " gcloud builds submit --config=cloudbuild.yaml"
|
||||
0
storage/keys/crewsportswear_app.key
Executable file → Normal file
0
storage/keys/crewsportswear_app.ppk
Executable file → Normal file
@@ -1,17 +0,0 @@
|
||||
# Traefik Dynamic Configuration for Custom SSL Certificates
|
||||
# This file should be uploaded to /srv/traefik/dynamic/traefik-certs.yml on production server
|
||||
|
||||
tls:
|
||||
certificates:
|
||||
# Production SSL Certificate (DigiCert)
|
||||
# Note: merchbay.com.crt should be a bundle containing www_merchbay_com.crt + DigiCertCA.crt
|
||||
- certFile: /srv/certs/merchbay.com.crt
|
||||
keyFile: /srv/certs/merchbay.com.key
|
||||
stores:
|
||||
- default
|
||||
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
certFile: /srv/certs/merchbay.com.crt
|
||||
keyFile: /srv/certs/merchbay.com.key
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
// yakpro-po configuration for Laravel 5.0
|
||||
|
||||
$conf = new StdClass;
|
||||
|
||||
// Directories to obfuscate (relative to project root)
|
||||
$conf->t_directories = [
|
||||
'app'
|
||||
];
|
||||
|
||||
// Directories/files to skip
|
||||
$conf->t_skip = [
|
||||
'vendor',
|
||||
'storage',
|
||||
'bootstrap',
|
||||
'config',
|
||||
'database',
|
||||
'public',
|
||||
'resources',
|
||||
'tests',
|
||||
'.env',
|
||||
'.env.example',
|
||||
'artisan',
|
||||
'server.php'
|
||||
];
|
||||
|
||||
// Obfuscation options
|
||||
$conf->obfuscate_string_literal = false; // Don't obfuscate strings (can break Laravel)
|
||||
$conf->obfuscate_function_name = true; // Obfuscate function names
|
||||
$conf->obfuscate_class_name = true; // Obfuscate class names (except Laravel core)
|
||||
$conf->obfuscate_variable_name = true; // Obfuscate variable names
|
||||
$conf->obfuscate_property_name = true; // Obfuscate property names
|
||||
$conf->obfuscate_class_constant_name = true;
|
||||
$conf->obfuscate_constant_name = true;
|
||||
$conf->obfuscate_namespace_name = false; // Keep namespaces readable
|
||||
$conf->obfuscate_label_name = true;
|
||||
|
||||
// Keep Laravel framework methods/classes readable
|
||||
$conf->t_ignore_constants = ['APP_ENV', 'APP_DEBUG', 'APP_URL', 'APP_KEY'];
|
||||
$conf->t_ignore_methods = [
|
||||
'__construct', '__destruct', '__call', '__get', '__set',
|
||||
'boot', 'register', 'handle', 'middleware', 'authorize'
|
||||
];
|
||||
|
||||
// Scrambler mode
|
||||
$conf->scrambler = true;
|
||||
|
||||
// Allow multiple PHP versions
|
||||
$conf->allow_and_operator = true;
|
||||
|
||||
// Output directory (will be overridden in command)
|
||||
$conf->t_dir = null;
|
||||
|
||||
return $conf;
|
||||