Skip to content

Commit a952905

Browse files
authored
main <- develop (#392)
1 parent fce0f8b commit a952905

File tree

960 files changed

+63099
-17480
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

960 files changed

+63099
-17480
lines changed

.github/workflows/deploy.yml

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
name: Deploy to Vapor and Frontend
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- develop
8+
workflow_dispatch:
9+
inputs:
10+
environment:
11+
description: 'Environment to deploy to'
12+
required: true
13+
default: 'staging'
14+
type: choice
15+
options:
16+
- staging
17+
- production
18+
test_mode:
19+
description: 'Run in test mode (no actual deployment)'
20+
required: false
21+
default: false
22+
type: boolean
23+
24+
jobs:
25+
backend:
26+
name: Deploy Backend
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- uses: actions/checkout@v3
31+
32+
- name: Setup PHP
33+
uses: shivammathur/setup-php@v2
34+
with:
35+
php-version: 8.3
36+
tools: composer:v2
37+
coverage: none
38+
39+
- name: Prepare Laravel Environment
40+
working-directory: ./backend
41+
run: |
42+
mkdir -p bootstrap/cache
43+
chmod -R 775 bootstrap/cache
44+
45+
- name: Prepare HTMLPurifier Cache Directory
46+
working-directory: ./backend
47+
run: |
48+
mkdir -p storage/app/htmlpurifier
49+
chmod -R 775 storage/app/htmlpurifier
50+
51+
- name: Install Dependencies
52+
working-directory: ./backend
53+
run: composer install --no-dev --no-progress --no-scripts --optimize-autoloader
54+
55+
- name: Install Vapor CLI
56+
run: composer global require laravel/vapor-cli
57+
58+
- name: Set Deployment Environment
59+
run: |
60+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
61+
echo "VAPOR_ENV=${{ github.event.inputs.environment }}" >> "$GITHUB_ENV"
62+
echo "TEST_MODE=${{ github.event.inputs.test_mode }}" >> "$GITHUB_ENV"
63+
elif [[ "${{ github.ref_name }}" == "develop" ]]; then
64+
echo "VAPOR_ENV=staging" >> "$GITHUB_ENV"
65+
echo "TEST_MODE=false" >> "$GITHUB_ENV"
66+
else
67+
echo "VAPOR_ENV=production" >> "$GITHUB_ENV"
68+
echo "TEST_MODE=false" >> "$GITHUB_ENV"
69+
fi
70+
71+
- name: Log Branch and Environment
72+
run: |
73+
echo "🚀 Deploying branch ${{ github.ref_name }} to Vapor environment: ${{ env.VAPOR_ENV }}"
74+
echo "🧪 Test mode: ${{ env.TEST_MODE }}"
75+
76+
- name: Validate Deployment Configuration
77+
working-directory: ./backend
78+
run: |
79+
if [[ "${{ env.TEST_MODE }}" == "true" ]]; then
80+
echo "✅ TEST MODE: Would deploy to ${{ env.VAPOR_ENV }} environment"
81+
echo "vapor deploy ${{ env.VAPOR_ENV }} --dry-run"
82+
exit 0
83+
fi
84+
85+
- name: Deploy to Vapor
86+
working-directory: ./backend
87+
run: vapor deploy ${{ env.VAPOR_ENV }}
88+
env:
89+
VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
90+
91+
frontend:
92+
name: Deploy Frontend
93+
runs-on: ubuntu-latest
94+
needs: backend
95+
96+
steps:
97+
- uses: actions/checkout@v3
98+
99+
- name: Set Deployment Environment
100+
run: |
101+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
102+
if [[ "${{ github.event.inputs.environment }}" == "staging" ]]; then
103+
echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_STAGING_APP_ID }}" >> "$GITHUB_ENV"
104+
else
105+
echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_PRODUCTION_APP_ID }}" >> "$GITHUB_ENV"
106+
fi
107+
echo "TEST_MODE=${{ github.event.inputs.test_mode }}" >> "$GITHUB_ENV"
108+
elif [[ "${{ github.ref_name }}" == "develop" ]]; then
109+
echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_STAGING_APP_ID }}" >> "$GITHUB_ENV"
110+
echo "TEST_MODE=false" >> "$GITHUB_ENV"
111+
else
112+
echo "DO_APP_ID=${{ secrets.DIGITALOCEAN_PRODUCTION_APP_ID }}" >> "$GITHUB_ENV"
113+
echo "TEST_MODE=false" >> "$GITHUB_ENV"
114+
fi
115+
116+
- name: Log Environment Settings
117+
run: |
118+
echo "🚀 Deploying frontend to DigitalOcean App: ${{ env.DO_APP_ID }}"
119+
echo "🧪 Test mode: ${{ env.TEST_MODE }}"
120+
121+
- name: Validate Deployment Configuration (Test Mode)
122+
if: env.TEST_MODE == 'true'
123+
run: |
124+
echo "✅ TEST MODE: Would trigger deployment for DigitalOcean App: ${{ env.DO_APP_ID }}"
125+
echo "curl -X POST 'https://api.digitalocean.com/v2/apps/${{ env.DO_APP_ID }}/deployments'"
126+
exit 0
127+
128+
- name: Trigger Deployment on DigitalOcean
129+
if: env.TEST_MODE != 'true'
130+
id: trigger_deployment
131+
run: |
132+
RESPONSE=$(curl -s -o response.json -w "%{http_code}" -X POST "https://api.digitalocean.com/v2/apps/$DO_APP_ID/deployments" \
133+
-H "Authorization: Bearer ${{ secrets.DIGITALOCEAN_API_TOKEN }}" \
134+
-H "Content-Type: application/json")
135+
136+
if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 200 ]; then
137+
ERROR_MSG=$(jq -r '.message // "Unknown error occurred."' response.json)
138+
echo "❌ Failed to trigger deployment. HTTP Status: $RESPONSE. Error: $ERROR_MSG"
139+
exit 1
140+
fi
141+
142+
DEPLOYMENT_ID=$(jq -r '.deployment.id' response.json)
143+
if [ "$DEPLOYMENT_ID" == "null" ]; then
144+
echo "❌ Failed to extract deployment ID."
145+
exit 1
146+
fi
147+
148+
echo "::add-mask::$DEPLOYMENT_ID"
149+
echo "✅ Deployment triggered successfully."
150+
151+
echo "deployment_id=$DEPLOYMENT_ID" >> "$GITHUB_ENV"
152+
153+
- name: Poll Deployment Status
154+
if: env.TEST_MODE != 'true'
155+
run: |
156+
MAX_RETRIES=60
157+
SLEEP_TIME=10
158+
COUNTER=0
159+
160+
while [ $COUNTER -lt $MAX_RETRIES ]; do
161+
RESPONSE=$(curl -s -X GET "https://api.digitalocean.com/v2/apps/$DO_APP_ID/deployments/${{ env.deployment_id }}" \
162+
-H "Authorization: Bearer ${{ secrets.DIGITALOCEAN_API_TOKEN }}" \
163+
-H "Content-Type: application/json")
164+
165+
STATUS=$(echo "$RESPONSE" | jq -r '.deployment.phase')
166+
167+
echo "🔄 Deployment Status: $STATUS"
168+
169+
if [ "$STATUS" == "ACTIVE" ]; then
170+
echo "✅ Deployment completed successfully."
171+
exit 0
172+
elif [[ "$STATUS" == "FAILED" || "$STATUS" == "CANCELLED" ]]; then
173+
echo "❌ Deployment failed or was cancelled."
174+
exit 1
175+
fi
176+
177+
COUNTER=$((COUNTER + 1))
178+
echo "⏳ Retrying in $SLEEP_TIME seconds... ($COUNTER/$MAX_RETRIES)"
179+
sleep $SLEEP_TIME
180+
done
181+
182+
echo "⏰ Deployment timed out."
183+
exit 1

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
frontend/.env
77
backend/.env
88
todo.md
9+
10+
.vercel

Dockerfile.all-in-one

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,19 @@ RUN apk add --no-cache nodejs yarn nginx supervisor
2121
COPY --from=node-frontend /app/frontend /app/frontend
2222

2323
COPY ./backend /app/backend
24-
RUN chown -R www-data:www-data /app/backend \
24+
RUN mkdir -p /app/backend/bootstrap/cache \
25+
&& mkdir -p /app/backend/storage \
26+
&& chown -R www-data:www-data /app/backend \
2527
&& find /app/backend -type d -exec chmod 755 {} \; \
2628
&& find /app/backend -type f -exec chmod 644 {} \; \
27-
&& chmod -R 777 /app/backend/storage /app/backend/bootstrap/cache \
29+
&& chmod -R 755 /app/backend/storage /app/backend/bootstrap/cache \
2830
&& composer install --working-dir=/app/backend \
2931
--ignore-platform-reqs \
3032
--no-interaction \
3133
--no-dev \
3234
--optimize-autoloader \
3335
--prefer-dist \
34-
&& chmod -R 777 /app/backend/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer
36+
&& chmod -R 755 /app/backend/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer
3537

3638
COPY ./docker/all-in-one/nginx/nginx.conf /etc/nginx/nginx.conf
3739
COPY ./docker/all-in-one/supervisor/supervisord.conf /etc/supervisord.conf

README.md

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
<img src="https://hievents-public.s3.us-west-1.amazonaws.com/website/hi-events-rainbow.png?v=1" alt="Hi.Events Logo" width="200px">
77
</p>
88

9-
109
<h3 align="center">Hi.Events</h3>
1110

1211
<p align="center">
13-
<a href="https://demo.hi.events/event/1/dog-conf-2030">Demo Event 🌟</a> • <a href="https://hi.events?utm_source=gh-readme">Website 🌎</a> • <a href="https://hi.events/docs">Documentation 📄</a> • <a href="https://hi.events/docs/getting-started?utm_source=gh-readme">Installation ⚙️</a>
12+
<a href="https://demo.hi.events/event/1/dog-conf-2030">Demo Event 🌟</a> • <a href="https://hi.events?utm_source=gh-readme">Website 🌎</a> • <a href="https://hi.events/docs?utm_source=gh-readme">Documentation 📄</a> • <a href="https://hi.events/docs/getting-started?utm_source=gh-readme">Installation ⚙️</a>
1413
</p>
1514

1615
<h3 align="center">
@@ -59,34 +58,55 @@
5958
<a href="https://hi.events">Hi.Events</a> is a feature-rich, self-hosted event management and ticketing platform. From conferences to club nights,
6059
Hi.Events is designed to help you create, manage, and sell tickets for events of all sizes.
6160

62-
<img alt="Hi.Events self-hosted ticket selling dashboard" src="https://hievents-public.s3.us-west-1.amazonaws.com/website/dashboard-screenshot.png"/>
61+
<img alt="Hi.Events self-hosted ticket selling dashboard" src="https://hievents-public.s3.us-west-1.amazonaws.com/website/github-readme-screenshot.png"/>
62+
<caption>Generated using <a href="https://screenshot.rocks?utm_source=hi.events-readme">Screenshot Rocks</a></caption>
6363

6464
## 🌟 Features
6565

6666
<a href="https://hi.events">Hi.Events</a> is packed with features to streamline your event management and ticketing:
6767

68-
- 📊 **Event Analytics:** Gain deep insights into event performance and ticket sales.
69-
- 🎟 **Embeddable Ticket Widget:** Easily integrate ticket sales into any website.
70-
- 🖥 **Customizable Event Homepages:** Create eye-catching event pages with flexible design options.
71-
- 🔑 **Intuitive Check-In Tools:** Easily check in attendees at the door with Hi.Events' QR code check-in tool.
72-
- 💬 **Event Messaging Tools:** Message attendees with important updates and reminders.
73-
- 📝 **Custom Order Forms:** Collect attendee information with tailored questions at checkout.
74-
- 🎫 **Multiple Ticket Types:** Free, paid, donation, or tiered ticket types.
75-
- 💸 **Versatile Promo Codes:** Highly versatile discount codes. Pre-sale access, multiple discount options.
76-
- 💰 **Instant Payouts:** Enjoy instant payouts with seamless Stripe integration.
77-
- 🧾 **Tax and Fee Configuration:** Add tax and fees on a per-ticket basis.
78-
- 📦 **Data Exports:** Export attendee and order data to XLSX or CSV.
79-
- 💻 **REST API:** Full-featured REST API for custom integrations.
80-
- 🔍 **SEO Tools:** Customize SEO settings for each event.
81-
- 🛒 **Beautiful Checkout Process:** Ensure a smooth, beautiful checkout experience.
82-
- 🔐 **Role-Based Access:** Support for multiple user roles.
83-
- 💻 **Online Event Support:** Offer online event instructions and links.
84-
-**Full and Partial Refund Support:** Manage full and partial refunds with ease.
85-
- 📧 **Email Notifications:** Keep attendees informed with automated email notifications.
86-
- 📱 **Mobile-Responsive:** Enjoy a seamless experience on any device.
87-
- 🌐 **Multi-Language Support:** Support for multiple languages (English, Português, Español, 中文 (Zhōngwén), Deutsch, Français)
88-
- 🔋 **Advanced Capacity Management:** Set capacity limits across multiple ticket types.
89-
- 🎉 **And much more!**
68+
### 🎟 Ticketing & Product Sales
69+
- **Multiple Ticket Types:** Free, Paid, Donation, and Tiered tickets.
70+
- **Capacity Management:** Set event-wide or ticket-specific limits.
71+
- **Capacity Assignments:** Manage shared capacity across multiple ticket types.
72+
- **Promo Codes:** Discount codes for pre-sale access and special offers.
73+
- **Product Sales:** Sell event-related products (e.g., t-shirts, add-ons).
74+
- **Taxes & Fees:** Apply custom taxes and fees per product or order.
75+
76+
### 🏆 Event Management & Customization
77+
- **Event Dashboard:** Real-time revenue, ticket sales, and attendee analytics.
78+
- **Homepage Designer:** Customize event pages with a live preview editor.
79+
- **Embeddable Ticket Widget:** Add a seamless ticketing experience to your website.
80+
- **SEO Tools:** Customize event metadata for better search visibility.
81+
- **Product Categories:** Organize products and tickets with category management.
82+
- **Offline Event Support:** Provide instructions for physical events.
83+
84+
### 📧 Attendee & Order Management
85+
- **Custom Checkout Forms:** Collect attendee details with tailored questions.
86+
- **Attendee Management:** Search, edit, cancel, and message attendees.
87+
- **Order Management:** Refund, cancel, and resend order details easily.
88+
- **Bulk Messaging:** Email or message specific ticket holders.
89+
- **Data Exports:** Export attendees and orders to CSV/XLSX.
90+
91+
### 📱 Mobile-Friendly & Check-In Tools
92+
- **QR Code Check-In:** Web-based and mobile-friendly check-in tool.
93+
- **Check-In Lists:** Generate and share access-controlled check-in lists.
94+
- **Multi-User Access:** Role-based access control for event staff.
95+
96+
### 🔧 Integrations & Automation
97+
- **Webhooks Support:** Automate tasks with Zapier, IFTTT, Make, or CRM integrations.
98+
- **Stripe Connect Integration:** Organizers get instant payouts.
99+
100+
### 📊 Advanced Features
101+
- **Multi-Language Support:** English, Deutsch, Español, Português, Français, 中文 (Zhōngwén), and more.
102+
- **Partial & Full Refunds:** Manage refunds with detailed order tracking.
103+
- **Role-Based Access Control:** Multiple user roles with permission management.
104+
- **REST API:** Full API access for custom integrations.
105+
- **Invoicing System:** Generate and send invoices with tax details, payment terms, and due dates.
106+
- **Offline Payment Support:** Enable bank transfers, cash payments, or custom payment methods.
107+
- **Event Archive:** Archive past events to keep the dashboard organized.
108+
- **Advanced Ticket Locking:** Lock tickets behind promo codes or access restrictions.
109+
- **Advanced Reporting:** Daily sales, tax breakdowns, product sales, and promo code usage reports.
90110

91111
## 🚀 Getting Started
92112

backend/.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ APP_SAAS_MODE_ENABLED=false
1111
APP_SAAS_STRIPE_APPLICATION_FEE_PERCENT=1.5
1212
APP_HOMEPAGE_VIEWS_UPDATE_BATCH_SIZE=8
1313
APP_DISABLE_REGISTRATION=false
14+
APP_STRIPE_CONNECT_ACCOUNT_TYPE=express
15+
APP_PLATFORM_SUPPORT_EMAIL=[email protected]
1416

1517
STRIPE_PUBLIC_KEY=
1618
STRIPE_SECRET_KEY=
1719
STRIPE_WEBHOOK_SECRET=
1820

19-
CORS_ALLOWED_ORIGINS=http://localhost:5173
21+
CORS_ALLOWED_ORIGINS=*
2022

2123
LOG_CHANNEL=stderr
2224
LOG_DEPRECATIONS_CHANNEL=null

backend/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
.env
99
.env.backup
1010
.env.production
11+
.env.staging
1112
.phpunit.result.cache
1213
Homestead.json
1314
Homestead.yaml
@@ -19,3 +20,4 @@ yarn-error.log
1920
/.vscode
2021
.idea
2122
/app-back
23+
bootstrap/cache
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace HiEvents\DomainObjects;
4+
5+
class AccountConfigurationDomainObject extends Generated\AccountConfigurationDomainObjectAbstract
6+
{
7+
public function getFixedApplicationFee(): float
8+
{
9+
return $this->getApplicationFees()['fixed'] ?? config('app.default_application_fee_fixed');
10+
}
11+
12+
public function getPercentageApplicationFee(): float
13+
{
14+
return $this->getApplicationFees()['percentage'] ?? config('app.default_application_fee_percentage');
15+
}
16+
}

backend/app/DomainObjects/AccountDomainObject.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22

33
namespace HiEvents\DomainObjects;
44

5+
use HiEvents\DomainObjects\DTO\AccountApplicationFeeDTO;
6+
57
class AccountDomainObject extends Generated\AccountDomainObjectAbstract
68
{
9+
private ?AccountConfigurationDomainObject $configuration = null;
10+
11+
public function getApplicationFee(): AccountApplicationFeeDTO
12+
{
13+
/** @var AccountConfigurationDomainObject $applicationFee */
14+
$applicationFee = $this->getConfiguration();
15+
16+
return new AccountApplicationFeeDTO(
17+
$applicationFee->getPercentageApplicationFee(),
18+
$applicationFee->getFixedApplicationFee()
19+
);
20+
}
21+
22+
public function getConfiguration(): ?AccountConfigurationDomainObject
23+
{
24+
return $this->configuration;
25+
}
26+
27+
public function setConfiguration(AccountConfigurationDomainObject $configuration): void
28+
{
29+
$this->configuration = $configuration;
30+
}
731
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace HiEvents\DomainObjects;
4+
5+
class ApplicationFeeDomainObject extends Generated\ApplicationFeeDomainObjectAbstract
6+
{
7+
}

0 commit comments

Comments
 (0)