Compare commits
4 Commits
unfinished
...
PROD_1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f197490606 | ||
|
|
f26c9c274b | ||
|
|
54278c568d | ||
|
|
c68f28aa11 |
@@ -1,63 +0,0 @@
|
||||
# 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
|
||||
@@ -1,229 +0,0 @@
|
||||
# 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/)
|
||||
12
Dockerfile
Normal file → Executable file
@@ -11,23 +11,29 @@ RUN apk --update --no-cache add \
|
||||
zip \
|
||||
unzip \
|
||||
libmcrypt-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install gd pdo pdo_mysql zip mcrypt
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Clear cache
|
||||
# RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 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
|
||||
RUN chown -R www-data:www-data storage bootstrap
|
||||
|
||||
# Install Composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Install Laravel dependencies
|
||||
RUN composer install --no-interaction --no-plugins --no-scripts
|
||||
RUN composer install --no-plugins --no-scripts
|
||||
|
||||
# Generate Laravel application key
|
||||
RUN php artisan key:generate
|
||||
|
||||
# Create directory for the socket and set permissions
|
||||
RUN mkdir -p /run/php && chown www-data:www-data /run/php
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
# 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"]
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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"]
|
||||
@@ -1,132 +0,0 @@
|
||||
# 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"]
|
||||
@@ -1,86 +0,0 @@
|
||||
# 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"]
|
||||
@@ -1,75 +0,0 @@
|
||||
# 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"]
|
||||
@@ -1,60 +0,0 @@
|
||||
# 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,100 +0,0 @@
|
||||
# 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,7 +399,8 @@ class PaypalController extends Controller
|
||||
public function getTax($cartKey)
|
||||
{
|
||||
$m = new TeamStoreModel;
|
||||
$updated_getSubtotal = $m->getSubtotal($cartKey);
|
||||
$updated_getSubtotal = $m->getSubtotalNew($cartKey);
|
||||
$original_subtotal = $m->getSubtotal($cartKey); // withoutTanle
|
||||
$grouped_item = $m->selectTeamStoreGroupByCartKey($cartKey);
|
||||
|
||||
if (count($grouped_item) <= 0) {
|
||||
@@ -414,10 +415,11 @@ class PaypalController extends Controller
|
||||
|
||||
|
||||
$order_grandtotal = $updated_getSubtotal[0]->Subtotal;
|
||||
$order_subtotal = $original_subtotal[0]->Subtotal;
|
||||
|
||||
|
||||
|
||||
$tax = $order_grandtotal * $tax_value;
|
||||
$tax = $order_subtotal * $tax_value;
|
||||
|
||||
return [
|
||||
'tax' => $tax,
|
||||
|
||||
@@ -499,6 +499,30 @@ 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'];
|
||||
@@ -954,6 +978,7 @@ 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 {
|
||||
|
||||
@@ -348,14 +348,16 @@ 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('shipping_cost', $shipping_cost)
|
||||
->with('roster', $roster);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1344,4 +1346,76 @@ 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,6 +149,11 @@ 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,6 +189,16 @@ 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,4 +425,44 @@ 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
|
||||
}
|
||||
}
|
||||
156
cloudbuild.yaml
@@ -1,156 +0,0 @@
|
||||
# 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,75 +0,0 @@
|
||||
# Docker Compose for local development and testing
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.basic
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
- APP_ENV=local
|
||||
- APP_DEBUG=true
|
||||
- APP_KEY=base64:your-app-key-here
|
||||
- DB_HOST=mysql
|
||||
- DB_DATABASE=merchbay
|
||||
- DB_USERNAME=laravel_user
|
||||
- DB_PASSWORD=secret
|
||||
- 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
|
||||
volumes:
|
||||
- ./storage:/var/www/html/storage
|
||||
- ./bootstrap/cache:/var/www/html/bootstrap/cache
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
networks:
|
||||
- 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: phpmyadmin/phpmyadmin
|
||||
environment:
|
||||
- PMA_HOST=mysql
|
||||
- PMA_USER=root
|
||||
- PMA_PASSWORD=root
|
||||
ports:
|
||||
- "8081:80"
|
||||
depends_on:
|
||||
- mysql
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
0
docker-compose.yml
Normal file → Executable file
0
favicon.ico
Normal file → Executable file
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
30
nginx/conf.d/app.conf
Normal file → Executable file
@@ -3,29 +3,37 @@ server {
|
||||
index index.php index.html;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /var/www/public;
|
||||
root /var/www;
|
||||
index index.php index.html;
|
||||
|
||||
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;
|
||||
}
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass app:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_pass app:9000;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~* \.(css|less|js|jpg|png|gif)$ {
|
||||
expires 0;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
expires 0;
|
||||
}
|
||||
|
||||
}
|
||||
0
php/local.ini
Normal file → Executable file
0
public/api/canada.json
Normal file → Executable file
0
public/api/usa.json
Normal file → Executable file
0
public/api/usaCities.old.json
Normal file → Executable file
0
public/assets/css/jquery-ui.css
vendored
Normal file → Executable file
0
public/assets/files/Terms of Use.pdf
Normal file → Executable file
0
public/assets/js/jquery-ui.js
vendored
Normal file → Executable file
0
public/images/MERCHBAY-LOGO.png
Normal file → Executable file
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
public/images/merchbay-black.png
Normal file → Executable file
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
0
public/images/merchbay-white.png
Normal file → Executable file
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
106
rebuild.sh
@@ -1,106 +0,0 @@
|
||||
#!/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
Normal file → Executable file
0
resources/views/emails/contact_us.blade.php
Normal file → Executable file
@@ -540,6 +540,13 @@
|
||||
<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 -->
|
||||
@@ -666,6 +673,17 @@
|
||||
<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
Normal file → Executable file
@@ -174,6 +174,15 @@
|
||||
<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
|
||||
|
||||
@@ -296,6 +305,17 @@
|
||||
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
Normal file → Executable file
0
resources/views/merchbay/privacy_policy.blade.php
Normal file → Executable file
0
resources/views/merchbay/terms_of_use.blade.php
Normal file → Executable file
0
resources/views/merchbay/track_order.blade.php
Normal file → Executable file
@@ -10,11 +10,11 @@
|
||||
<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('public/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('public/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>
|
||||
@@ -258,7 +258,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) {
|
||||
@@ -307,7 +307,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++) {
|
||||
|
||||
0
resources/views/paypal/payment_success.blade.php
Normal file → Executable file
45
resources/views/teamstore-sublayouts/forms/number-size-form.blade.php
Executable file
@@ -0,0 +1,45 @@
|
||||
|
||||
<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
Normal file → Executable file
@@ -7,11 +7,12 @@
|
||||
margin-top:20px;
|
||||
}
|
||||
</style>
|
||||
<div class="content-wrapper" style="min-height: 916px;">
|
||||
<div class="content-wrapper" id="addItem" style="min-height: 916px;">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Add Store Item
|
||||
{{-- <p>@{{ message }}</p> --}}
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url('user') }}"><i class="fa fa-home"></i> Home</a></li>
|
||||
@@ -92,6 +93,9 @@
|
||||
</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>
|
||||
@@ -102,6 +106,7 @@
|
||||
<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,7 +125,8 @@
|
||||
<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-number-size-form">Name, Number and Size 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="number-form">Number Only Form</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -114,6 +114,13 @@
|
||||
<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
|
||||
@@ -195,6 +202,13 @@
|
||||
<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,6 +158,14 @@
|
||||
<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
|
||||
@@ -219,6 +227,13 @@
|
||||
<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,6 +127,7 @@
|
||||
<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">
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
<!-- jquery-ui -->
|
||||
<link href="{{ asset('/public/assets/css/jquery-ui.css') }}" rel="stylesheet">
|
||||
<link href="{{asset('/public/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>
|
||||
<!-- 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]>
|
||||
@@ -2150,7 +2154,6 @@
|
||||
|
||||
function submitFormItemDetails() {
|
||||
var data = $("#frm-item-details").serialize();
|
||||
// console.log(data)
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: "{{ url('user/store-items/update') }}",
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
@extends('user-layouts.user_template')
|
||||
@section('content')
|
||||
<style>
|
||||
<style>
|
||||
.hide-bullets {
|
||||
list-style: none;
|
||||
margin-left: -40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
<div class="content-wrapper" style="min-height: 916px;">
|
||||
</style>
|
||||
|
||||
|
||||
<div class="content-wrapper" id="viewStoreItem" style="min-height: 916px;">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Store Item
|
||||
@{{ title }}
|
||||
<small>{{ $product_array[0]->ProductName }}</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
@@ -26,17 +28,22 @@
|
||||
<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>
|
||||
<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">
|
||||
@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>
|
||||
@@ -45,25 +52,35 @@
|
||||
<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;">
|
||||
<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') }}" />
|
||||
<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)
|
||||
@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;">
|
||||
<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() }}" />
|
||||
<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>
|
||||
<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>
|
||||
@@ -91,14 +108,17 @@
|
||||
<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">
|
||||
<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">
|
||||
<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">
|
||||
<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>
|
||||
@@ -119,46 +139,99 @@
|
||||
</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" />
|
||||
<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 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 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" />
|
||||
<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>
|
||||
<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>
|
||||
|
||||
@@ -167,7 +240,9 @@
|
||||
<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>
|
||||
<option value="{{ $sc->Id }}"
|
||||
@if ($sc->Id == $product_array[0]->ShippingCostId) selected @endif>
|
||||
{{ $sc->DisplayName }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span id="err_available_size"></span>
|
||||
@@ -186,10 +261,9 @@
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -206,14 +280,17 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sortable">
|
||||
@foreach($thumbnails_array as $thumbnail)
|
||||
|
||||
@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><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>
|
||||
<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
|
||||
@@ -223,15 +300,16 @@
|
||||
</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-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>
|
||||
|
||||
|
||||
<div class="modal fade" id="modal_add_thumbnail" role="dialog">
|
||||
<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">
|
||||
@@ -246,10 +324,12 @@
|
||||
<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/*" />
|
||||
<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>
|
||||
<button type="button" id="clear_frm_add_new_images"
|
||||
class="btn btn-default btn-block">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -271,7 +351,294 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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
|
||||
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</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');
|
||||
|
||||
|
||||
})
|
||||
.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
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/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"
|
||||