fix: add new stuffs to magicbar
feat: add user invitation command feat: add user_email function fix: update pricing plans
This commit is contained in:
parent
5a3457c180
commit
ee14d5caf5
77
app/Console/Commands/InviteFromWaitlist.php
Normal file
77
app/Console/Commands/InviteFromWaitlist.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Waitlist;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class InviteFromWaitlist extends Command
|
||||
{
|
||||
public Waitlist|null $next_patient = null;
|
||||
public User|null $new_user = null;
|
||||
public string|null $password = null;
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'app:invite-from-waitlist';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Send invitation to the next user in the waitlist';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->next_patient = Waitlist::orderBy('created_at', 'asc')->where('verified', true)->first();
|
||||
if ($this->next_patient) {
|
||||
$this->register_user();
|
||||
$this->remove_from_waitlist();
|
||||
$this->send_email();
|
||||
} else {
|
||||
$this->info('No one in the waitlist who is verified. 👀');
|
||||
}
|
||||
}
|
||||
private function register_user()
|
||||
{
|
||||
$already_registered = User::whereEmail($this->next_patient->email)->first();
|
||||
if (!$already_registered) {
|
||||
$this->password = Str::password();
|
||||
$this->new_user = User::create([
|
||||
'name' => Str::of($this->next_patient->email)->before('@'),
|
||||
'email' => $this->next_patient->email,
|
||||
'password' => Hash::make($this->password),
|
||||
'force_password_reset' => true,
|
||||
]);
|
||||
$this->info("User registered ({$this->next_patient->email}) successfully. 🎉");
|
||||
} else {
|
||||
throw new \Exception('User already registered');
|
||||
}
|
||||
}
|
||||
private function remove_from_waitlist()
|
||||
{
|
||||
$this->next_patient->delete();
|
||||
$this->info("User removed from waitlist successfully.");
|
||||
}
|
||||
private function send_email()
|
||||
{
|
||||
$mail = new MailMessage();
|
||||
$mail->view('emails.waitlist-invitation', [
|
||||
'email' => $this->next_patient->email,
|
||||
'password' => $this->password,
|
||||
]);
|
||||
$mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
||||
send_user_an_email($mail, $this->next_patient->email);
|
||||
$this->info("Email sent successfully. 📧");
|
||||
}
|
||||
}
|
72
app/Http/Livewire/Subscription/Actions.php
Normal file
72
app/Http/Livewire/Subscription/Actions.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Subscription;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Livewire\Component;
|
||||
|
||||
class Actions extends Component
|
||||
{
|
||||
public function cancel()
|
||||
{
|
||||
try {
|
||||
$subscription_id = auth()->user()->currentTeam()->subscription->lemon_subscription_id;
|
||||
if (!$subscription_id) {
|
||||
throw new \Exception('No subscription found');
|
||||
}
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/vnd.api+json',
|
||||
'Content-Type' => 'application/vnd.api+json',
|
||||
'Authorization' => 'Bearer ' . config('coolify.lemon_squeezy_api_key'),
|
||||
])->delete('https://api.lemonsqueezy.com/v1/subscriptions/' . $subscription_id);
|
||||
$json = $response->json();
|
||||
if ($response->failed()) {
|
||||
$error = data_get($json, 'errors.0.status');
|
||||
if ($error === '404') {
|
||||
throw new \Exception('Subscription not found.');
|
||||
}
|
||||
throw new \Exception(data_get($json, 'errors.0.title', 'Something went wrong. Please try again later.'));
|
||||
} else {
|
||||
$this->emit('success', 'Subscription cancelled successfully. Reloading in 5s.');
|
||||
$this->emit('reloadWindow', 5000);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return general_error_handler($e, $this);
|
||||
}
|
||||
}
|
||||
public function resume()
|
||||
{
|
||||
try {
|
||||
$subscription_id = auth()->user()->currentTeam()->subscription->lemon_subscription_id;
|
||||
if (!$subscription_id) {
|
||||
throw new \Exception('No subscription found');
|
||||
}
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/vnd.api+json',
|
||||
'Content-Type' => 'application/vnd.api+json',
|
||||
'Authorization' => 'Bearer ' . config('coolify.lemon_squeezy_api_key'),
|
||||
])->patch('https://api.lemonsqueezy.com/v1/subscriptions/' . $subscription_id, [
|
||||
'data' => [
|
||||
'type' => 'subscriptions',
|
||||
'id' => $subscription_id,
|
||||
'attributes' => [
|
||||
'cancelled' => false,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$json = $response->json();
|
||||
if ($response->failed()) {
|
||||
$error = data_get($json, 'errors.0.status');
|
||||
if ($error === '404') {
|
||||
throw new \Exception('Subscription not found.');
|
||||
}
|
||||
throw new \Exception(data_get($json, 'errors.0.title', 'Something went wrong. Please try again later.'));
|
||||
} else {
|
||||
$this->emit('success', 'Subscription resumed successfully. Reloading in 5s.');
|
||||
$this->emit('reloadWindow', 5000);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return general_error_handler($e, $this);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ class Waitlist extends Component
|
||||
public function mount()
|
||||
{
|
||||
if (is_dev()) {
|
||||
$this->email = 'test@example.com';
|
||||
$this->email = 'waitlist@example.com';
|
||||
}
|
||||
}
|
||||
public function submit()
|
||||
@ -27,8 +27,7 @@ public function submit()
|
||||
try {
|
||||
$already_registered = User::whereEmail($this->email)->first();
|
||||
if ($already_registered) {
|
||||
$this->emit('success', 'You are already registered (Thank you 💜).');
|
||||
return;
|
||||
throw new \Exception('You are already on the waitlist or registered. <br>Please check your email to verify your email address or contact support.');
|
||||
}
|
||||
$found = ModelsWaitlist::where('email', $this->email)->first();
|
||||
if ($found) {
|
||||
@ -36,7 +35,7 @@ public function submit()
|
||||
$this->emit('error', 'You are already on the waitlist. <br>Please check your email to verify your email address.');
|
||||
return;
|
||||
}
|
||||
$this->emit('error', 'You are already on the waitlist.');
|
||||
$this->emit('error', 'You are already on the waitlist. <br>You will be notified when your turn comes. <br>Thank you.');
|
||||
return;
|
||||
}
|
||||
$waitlist = ModelsWaitlist::create([
|
||||
|
@ -24,10 +24,6 @@ public function __construct(public string $email, public string $uuid)
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
$settings = InstanceSettings::get();
|
||||
|
||||
|
||||
set_transanctional_email_settings($settings);
|
||||
$mail = new MailMessage();
|
||||
|
||||
$confirmation_url = base_url() . '/webhooks/waitlist/confirm?email=' . $this->email . '&confirmation_code=' . $this->uuid;
|
||||
@ -39,18 +35,7 @@ public function handle()
|
||||
'cancel_url' => $cancel_url,
|
||||
]);
|
||||
$mail->subject('You are on the waitlist!');
|
||||
Mail::send(
|
||||
[],
|
||||
[],
|
||||
fn(Message $message) => $message
|
||||
->from(
|
||||
data_get($settings, 'smtp_from_address'),
|
||||
data_get($settings, 'smtp_from_name')
|
||||
)
|
||||
->to($this->email)
|
||||
->subject($mail->subject)
|
||||
->html((string) $mail->render())
|
||||
);
|
||||
send_user_an_email($mail, $this->email);
|
||||
} catch (\Throwable $th) {
|
||||
send_internal_notification('SendConfirmationForWaitlistJob failed with error: ' . $th->getMessage());
|
||||
ray($th->getMessage());
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
use App\Notifications\Channels\SendsEmail;
|
||||
use App\Notifications\TransactionalEmails\ResetPassword as TransactionalEmailsResetPassword;
|
||||
use App\Notifications\TrnsactionalEmails\ResetPassword;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
@ -5,7 +5,10 @@
|
||||
use App\Notifications\Internal\GeneralNotification;
|
||||
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Mail\Message;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
use Nubs\RandomNameGenerator\All;
|
||||
@ -205,3 +208,20 @@ function send_internal_notification(string $message): void
|
||||
ray($th->getMessage());
|
||||
}
|
||||
}
|
||||
function send_user_an_email(MailMessage $mail, string $email): void
|
||||
{
|
||||
$settings = InstanceSettings::get();
|
||||
set_transanctional_email_settings($settings);
|
||||
Mail::send(
|
||||
[],
|
||||
[],
|
||||
fn (Message $message) => $message
|
||||
->from(
|
||||
data_get($settings, 'smtp_from_address'),
|
||||
data_get($settings, 'smtp_from_name')
|
||||
)
|
||||
->to($email)
|
||||
->subject($mail->subject)
|
||||
->html((string) $mail->render())
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
'waitlist' => env('WAITLIST', false),
|
||||
'license_url' => 'https://license.coolify.io',
|
||||
'lemon_squeezy_api_key' => env('LEMON_SQUEEZY_API_KEY', null),
|
||||
'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET', null),
|
||||
'lemon_squeezy_checkout_id_monthly_basic' => env('LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_BASIC', null),
|
||||
'lemon_squeezy_checkout_id_monthly_pro' => env('LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_PRO', null),
|
||||
|
@ -128,6 +128,15 @@
|
||||
<path d="M4.571 18c1.5 0 2.047 -.074 2.958 -.78" />
|
||||
<path d="M10 16l0 .01" />
|
||||
</template>
|
||||
<template
|
||||
v-if="action.icon === 'storage' || sequenceState.sequence[sequenceState.currentActionIndex] === 'storage'">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2">
|
||||
<path d="M4 6a8 3 0 1 0 16 0A8 3 0 1 0 4 6" />
|
||||
<path d="M4 6v6a8 3 0 0 0 16 0V6" />
|
||||
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
|
||||
</g>
|
||||
</template>
|
||||
<template
|
||||
v-if="action.icon === 'project' || sequenceState.sequence[sequenceState.currentActionIndex] === 'project'">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
@ -273,6 +282,14 @@ const magicActions = [{
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Deploy: Dockerfile',
|
||||
tags: 'dockerfile,deploy',
|
||||
icon: 'destination',
|
||||
new: true,
|
||||
sequence: ['main', 'server', 'destination', 'project', 'environment', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Create: Server',
|
||||
tags: 'server,ssh,new,create',
|
||||
icon: 'server',
|
||||
@ -280,7 +297,7 @@ const magicActions = [{
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
id: 6,
|
||||
name: 'Create: Source',
|
||||
tags: 'source,git,gitlab,github,bitbucket,gitea,new,create',
|
||||
icon: 'git',
|
||||
@ -288,7 +305,7 @@ const magicActions = [{
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
id: 7,
|
||||
name: 'Create: Private Key',
|
||||
tags: 'private,key,ssh,new,create',
|
||||
icon: 'key',
|
||||
@ -296,16 +313,15 @@ const magicActions = [{
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
id: 8,
|
||||
name: 'Create: Destination',
|
||||
tags: 'destination,docker,network,new,create',
|
||||
icon: 'destination',
|
||||
new: true,
|
||||
sequence: ['main', 'server', 'redirect']
|
||||
},
|
||||
|
||||
{
|
||||
id: 8,
|
||||
id: 9,
|
||||
name: 'Create: Team',
|
||||
tags: 'team,member,new,create',
|
||||
icon: 'team',
|
||||
@ -313,74 +329,82 @@ const magicActions = [{
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
id: 10,
|
||||
name: 'Create: S3 Storage',
|
||||
tags: 's3,storage,new,create',
|
||||
icon: 'storage',
|
||||
new: true,
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Goto: Dashboard',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
id: 12,
|
||||
name: 'Goto: Servers',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
id: 13,
|
||||
name: 'Goto: Private Keys',
|
||||
tags: 'destination,docker,network,new,create,ssh,private,key',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
id: 14,
|
||||
name: 'Goto: Projects',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
id: 15,
|
||||
name: 'Goto: Sources',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
id: 16,
|
||||
name: 'Goto: Destinations',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
id: 17,
|
||||
name: 'Goto: Settings',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
id: 18,
|
||||
name: 'Goto: Command Center',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
id: 19,
|
||||
name: 'Goto: Notifications',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
id: 20,
|
||||
name: 'Goto: Profile',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
id: 21,
|
||||
name: 'Goto: Teams',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
id: 22,
|
||||
name: 'Goto: Switch Teams',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
@ -552,55 +576,63 @@ async function redirect() {
|
||||
targetUrl.searchParams.append('destination', destination)
|
||||
break;
|
||||
case 4:
|
||||
targetUrl.pathname = `/server/new`
|
||||
targetUrl.pathname = `/project/${project}/${environment}/new`
|
||||
targetUrl.searchParams.append('type', 'dockerfile')
|
||||
targetUrl.searchParams.append('destination', destination)
|
||||
break;
|
||||
case 5:
|
||||
targetUrl.pathname = `/source/new`
|
||||
targetUrl.pathname = `/server/new`
|
||||
break;
|
||||
case 6:
|
||||
targetUrl.pathname = `/private-key/new`
|
||||
targetUrl.pathname = `/source/new`
|
||||
break;
|
||||
case 7:
|
||||
targetUrl.pathname = `/private-key/new`
|
||||
break;
|
||||
case 8:
|
||||
targetUrl.pathname = `/destination/new`
|
||||
targetUrl.searchParams.append('server', server)
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
targetUrl.pathname = `/team/new`
|
||||
break;
|
||||
case 9:
|
||||
targetUrl.pathname = `/`
|
||||
break;
|
||||
case 10:
|
||||
targetUrl.pathname = `/servers`
|
||||
targetUrl.pathname = `/team/storages/new`
|
||||
break;
|
||||
case 11:
|
||||
targetUrl.pathname = `/private-keys`
|
||||
targetUrl.pathname = `/`
|
||||
break;
|
||||
case 12:
|
||||
targetUrl.pathname = `/projects`
|
||||
targetUrl.pathname = `/servers`
|
||||
break;
|
||||
case 13:
|
||||
targetUrl.pathname = `/sources`
|
||||
targetUrl.pathname = `/private-keys`
|
||||
break;
|
||||
case 14:
|
||||
targetUrl.pathname = `/destinations`
|
||||
targetUrl.pathname = `/projects`
|
||||
break;
|
||||
case 15:
|
||||
targetUrl.pathname = `/settings`
|
||||
targetUrl.pathname = `/sources`
|
||||
break;
|
||||
case 16:
|
||||
targetUrl.pathname = `/command-center`
|
||||
targetUrl.pathname = `/destinations`
|
||||
break;
|
||||
case 17:
|
||||
targetUrl.pathname = `/team/notifications`
|
||||
targetUrl.pathname = `/settings`
|
||||
break;
|
||||
case 18:
|
||||
targetUrl.pathname = `/profile`
|
||||
targetUrl.pathname = `/command-center`
|
||||
break;
|
||||
case 19:
|
||||
targetUrl.pathname = `/team`
|
||||
targetUrl.pathname = `/team/notifications`
|
||||
break;
|
||||
case 20:
|
||||
targetUrl.pathname = `/profile`
|
||||
break;
|
||||
case 21:
|
||||
targetUrl.pathname = `/team`
|
||||
break;
|
||||
case 22:
|
||||
targetUrl.pathname = `/team`
|
||||
break;
|
||||
}
|
||||
|
@ -58,8 +58,15 @@ function changePasswordFieldType(event) {
|
||||
}
|
||||
}
|
||||
|
||||
Livewire.on('reloadWindow', () => {
|
||||
Livewire.on('reloadWindow', (timeout) => {
|
||||
if (timeout) {
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, timeout);
|
||||
return;
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
@ -9,7 +9,7 @@
|
||||
@env('local')
|
||||
<title>Coolify - localhost</title>
|
||||
<link rel="icon" href="{{ asset('favicon-dev.png') }}" type="image/x-icon" />
|
||||
@else
|
||||
@else
|
||||
<title>{{ $title ?? 'Coolify' }}</title>
|
||||
<link rel="icon" href="{{ asset('coolify-transparent.png') }}" type="image/x-icon" />
|
||||
@endenv
|
||||
@ -101,8 +101,15 @@ function copyToClipboard(text) {
|
||||
Livewire.emit('message', 'Copied to clipboard.');
|
||||
}
|
||||
|
||||
Livewire.on('reloadWindow', () => {
|
||||
Livewire.on('reloadWindow', (timeout) => {
|
||||
if (timeout) {
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, timeout);
|
||||
return;
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
})
|
||||
Livewire.on('info', (message) => {
|
||||
if (message) Toaster.info(message)
|
||||
|
@ -50,6 +50,20 @@ class="{{ request()->is('command-center') ? 'text-warning icon' : 'icon' }}" vie
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li title="Teams">
|
||||
<a class="hover:bg-transparent" href="{{ route('team.show') }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
|
||||
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
|
||||
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<div class="flex-1"></div>
|
||||
@if (is_instance_admin())
|
||||
<livewire:upgrade />
|
||||
@ -65,20 +79,7 @@ class="{{ request()->is('command-center') ? 'text-warning icon' : 'icon' }}" vie
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li title="Teams">
|
||||
<a class="hover:bg-transparent" href="{{ route('team.show') }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
|
||||
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
|
||||
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@if (is_instance_admin())
|
||||
<li title="Settings" class="mt-auto">
|
||||
<a class="hover:bg-transparent" @if (!request()->is('settings')) href="/settings" @endif>
|
||||
|
@ -1,7 +1,7 @@
|
||||
@props([
|
||||
'showSubscribeButtons' => true,
|
||||
])
|
||||
<div x-data="{ selected: 'monthly' }" class="w-full pb-20">
|
||||
<div x-data="{ selected: 'yearly' }" class="w-full pb-20">
|
||||
<div class="px-6 mx-auto lg:px-8">
|
||||
<div class="flex justify-center mt-5">
|
||||
<fieldset
|
||||
@ -17,7 +17,7 @@ class="sr-only">
|
||||
:class="selected === 'yearly' ? 'bg-coollabs-100 text-white' : ''">
|
||||
<input type="radio" x-on:click="selected = 'yearly'" name="frequency" value="annually"
|
||||
class="sr-only">
|
||||
<span>Annually</span>
|
||||
<span>Annually <span class="text-xs text-warning">(save ~1 month)<span></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
@ -42,7 +42,12 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
<span class="text-4xl font-bold tracking-tight text-white">Still Free </span>
|
||||
</span>
|
||||
</p>
|
||||
<span x-show="selected === 'yearly'" x-cloak class="text-warning">(save $?)</span>
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span>billed monthly</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span>billed annually</span>
|
||||
</span>
|
||||
<a href="https://github.com/coollabsio/coolify" aria-describedby="tier-trial" class="buyme">Get
|
||||
Started</a>
|
||||
<p class="mt-10 text-sm leading-6 text-white h-[6.5rem]">Start self-hosting without limits with our
|
||||
@ -56,25 +61,7 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Same features as the paid version
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Managed by you
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
If you brave enough
|
||||
You manage everything
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
@ -104,19 +91,24 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
<p class="flex items-baseline mt-6 gap-x-1">
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$5</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/monthly</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$54</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/yearly</span>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$4</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
</p>
|
||||
<span x-show="selected === 'yearly'" x-cloak class="text-warning">(save $6)</span>
|
||||
@if(!$showSubscribeButtons)
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span>billed monthly</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span>billed annually</span>
|
||||
</span>
|
||||
@if ($showSubscribeButtons)
|
||||
<a x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" class="buyme"
|
||||
href="{{ getSubscriptionLink('monthly_basic') }}">Subscribe</a>
|
||||
<a x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" class="buyme"
|
||||
href="{{ getSubscriptionLink('yearly') }}">Subscribe</a>
|
||||
href="{{ getSubscriptionLink('yearly_basic') }}">Subscribe</a>
|
||||
@endif
|
||||
<p class="mt-10 text-sm leading-6 text-white h-[6.5rem]">Start self-hosting in
|
||||
the cloud
|
||||
@ -134,24 +126,6 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
</svg>
|
||||
1 server <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Unlimited Deployments
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Bring your own S3
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
@ -176,23 +150,28 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
|
||||
<h3 id="tier-essential" class="text-base font-semibold leading-7 text-white">Essential</h3>
|
||||
<h3 id="tier-pro" class="text-base font-semibold leading-7 text-white">Pro</h3>
|
||||
<p class="flex items-baseline mt-6 gap-x-1">
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$29</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/monthly</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$319</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/yearly</span>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$26</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
</p>
|
||||
<span x-show="selected === 'yearly'" x-cloak class="text-warning">(save $29)</span>
|
||||
@if(!$showSubscribeButtons)
|
||||
<a x-show="selected === 'monthly'" x-cloak aria-describedby="tier-essential" class="buyme"
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span>billed monthly</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span>billed annually</span>
|
||||
</span>
|
||||
@if ($showSubscribeButtons)
|
||||
<a x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" class="buyme"
|
||||
href="{{ getSubscriptionLink('monthly_pro') }}">Subscribe</a>
|
||||
<a x-show="selected === 'yearly'" x-cloak aria-describedby="tier-essential" class="buyme"
|
||||
href="{{ getSubscriptionLink('yearly') }}">Subscribe</a>
|
||||
<a x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="buyme"
|
||||
href="{{ getSubscriptionLink('yearly_pro') }}">Subscribe</a>
|
||||
@endif
|
||||
<p class="h-20 mt-10 text-sm leading-6 text-white">Scale your business or self-hosting environment.
|
||||
</p>
|
||||
@ -204,25 +183,7 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
1 server <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Unlimited Deployments
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Provided (optional) S3
|
||||
5 servers <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
@ -248,23 +209,28 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
|
||||
<h3 id="tier-growth" class="text-base font-semibold leading-7 text-white">Growth</h3>
|
||||
<h3 id="tier-ultimate" class="text-base font-semibold leading-7 text-white">Ultimate</h3>
|
||||
<p class="flex items-baseline mt-6 gap-x-1">
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$49</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/monthly</span>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$69</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$539</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/yearly</span>
|
||||
<span class="text-4xl font-bold tracking-tight text-white">$63</span>
|
||||
<span class="text-sm font-semibold leading-6 ">/month</span>
|
||||
</span>
|
||||
</p>
|
||||
<span x-show="selected === 'yearly'" x-cloak class="text-warning">(save $69)</span>
|
||||
@if(!$showSubscribeButtons)
|
||||
<a x-show="selected === 'monthly'" x-cloak aria-describedby="tier-growth" class="buyme"
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span>billed monthly</span>
|
||||
</span>
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span>billed annually</span>
|
||||
</span>
|
||||
@if ($showSubscribeButtons)
|
||||
<a x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" class="buyme"
|
||||
href="{{ getSubscriptionLink('monthly_ultimate') }}">Subscribe</a>
|
||||
<a x-show="selected === 'yearly'" x-cloak aria-describedby="tier-growth" class="buyme"
|
||||
href="{{ getSubscriptionLink('yearly') }}">Subscribe</a>
|
||||
<a x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" class="buyme"
|
||||
href="{{ getSubscriptionLink('yearly_ultimate') }}">Subscribe</a>
|
||||
@endif
|
||||
<p class="h-20 mt-10 text-sm leading-6 text-white">Deploy complex infrastuctures and
|
||||
manage them easily in one place.</p>
|
||||
@ -276,25 +242,7 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Unlimited servers <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Unlimited deployments
|
||||
</li>
|
||||
<li class="flex gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
Provided (optional) S3
|
||||
15 servers <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
|
||||
</li>
|
||||
<li class="flex font-bold text-white gap-x-3">
|
||||
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
|
||||
@ -320,6 +268,9 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-10">Need unlimited servers or official support for your Coolify instance? <a
|
||||
href="https://docs.coollabs.io/contact" class='text-warning'>Contact us.</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
13
resources/views/emails/waitlist-invitation.blade.php
Normal file
13
resources/views/emails/waitlist-invitation.blade.php
Normal file
@ -0,0 +1,13 @@
|
||||
Congratulations!<br>
|
||||
<br>
|
||||
You have been invited to join the Coolify Cloud: <a href="{{base_url()}}/login">Login here</a>
|
||||
<br>
|
||||
<br>
|
||||
Credentials:
|
||||
<br>
|
||||
Email: {{ $email }}
|
||||
<br>
|
||||
Password: {{ $password }}
|
||||
<br>
|
||||
(You will forced to change it on first login.)
|
||||
|
31
resources/views/livewire/subscription/actions.blade.php
Normal file
31
resources/views/livewire/subscription/actions.blade.php
Normal file
@ -0,0 +1,31 @@
|
||||
<div>
|
||||
<div>Status: {{ auth()->user()->currentTeam()->subscription->lemon_status }}</div>
|
||||
<div>Type: {{ auth()->user()->currentTeam()->subscription->lemon_variant_name }}</div>
|
||||
@if (auth()->user()->currentTeam()->subscription->lemon_status === 'cancelled')
|
||||
<div class="pb-4">Subscriptions ends at: {{ getRenewDate() }}</div>
|
||||
<div class="py-4">If you would like to change the subscription to a lower/higher plan, <a
|
||||
class="text-white underline" href="https://docs.coollabs.io/contact" target="_blank">please
|
||||
contact
|
||||
us.</a></div>
|
||||
@else
|
||||
<div class="pb-4">Renews at: {{ getRenewDate() }}</div>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
@if (auth()->user()->currentTeam()->subscription->lemon_status === 'cancelled')
|
||||
<x-forms.button class="bg-coollabs-gradient" wire:click='resume'>Resume Subscription
|
||||
</x-forms.button>
|
||||
@else
|
||||
<x-forms.button wire:click='cancel'>Cancel Subscription</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<x-forms.button><a class="text-white hover:no-underline" href="{{ getPaymentLink() }}">Update Payment
|
||||
Details</a>
|
||||
</x-forms.button>
|
||||
<a class="text-white hover:no-underline"
|
||||
href="https://app.lemonsqueezy.com/my-orders"><x-forms.button>Manage My
|
||||
Subscription</x-forms.button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -8,34 +8,13 @@
|
||||
<h2>Subscription</h2>
|
||||
@if (data_get(auth()->user()->currentTeam(),
|
||||
'subscription'))
|
||||
<div>Status: {{ auth()->user()->currentTeam()->subscription->lemon_status }}</div>
|
||||
<div>Type: {{ auth()->user()->currentTeam()->subscription->lemon_variant_name }}</div>
|
||||
@if (auth()->user()->currentTeam()->subscription->lemon_status === 'cancelled')
|
||||
<div class="pb-4">Subscriptions ends at: {{ getRenewDate() }}</div>
|
||||
<x-forms.button class="bg-coollabs-gradient"><a class="text-white hover:no-underline"
|
||||
href="{{ route('subscription') }}">Resume Subscription</a>
|
||||
</x-forms.button>
|
||||
<div class="py-4">If you would like to change the subscription to a lower/higher plan, <a
|
||||
class="text-white underline" href="https://docs.coollabs.io/contact" target="_blank">please
|
||||
contact
|
||||
us.</a></div>
|
||||
@else
|
||||
<div class="pb-4">Renews at: {{ getRenewDate() }}</div>
|
||||
@endif
|
||||
|
||||
|
||||
<x-forms.button><a class="text-white hover:no-underline" href="{{ getPaymentLink() }}">Update Payment
|
||||
Details</a>
|
||||
</x-forms.button>
|
||||
<livewire:subscription.actions />
|
||||
@else
|
||||
<x-forms.button class="mt-4"><a class="text-white hover:no-underline"
|
||||
href="{{ route('subscription') }}">Subscribe Now</a>
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button><a class="text-white hover:no-underline"
|
||||
href="https://app.lemonsqueezy.com/my-orders">Manage My
|
||||
Subscription</a>
|
||||
</x-forms.button>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
<livewire:team.delete />
|
||||
|
@ -190,7 +190,6 @@
|
||||
} catch (error) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
|
||||
})->name('webhooks.waitlist.confirm');
|
||||
Route::get('/waitlist/cancel', function () {
|
||||
$email = request()->get('email');
|
||||
@ -206,7 +205,6 @@
|
||||
} catch (error) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
|
||||
})->name('webhooks.waitlist.cancel');
|
||||
Route::post('/payments/events', function () {
|
||||
try {
|
||||
@ -251,7 +249,7 @@
|
||||
case 'subscription_updated':
|
||||
case 'subscription_resumed':
|
||||
case 'subscription_unpaused':
|
||||
send_internal_notification('Subscription created or updated: ' . $subscription_id . ' for team ' . $team_id . ' with status ' . $status);
|
||||
send_internal_notification("LemonSqueezy Event (`$event`): `" . $email . '` with status `' . $status . '`, tier: `' . $variant_name . '`');
|
||||
$subscription = Subscription::updateOrCreate([
|
||||
'team_id' => $team_id,
|
||||
], [
|
||||
@ -273,7 +271,7 @@
|
||||
case 'subscription_expired':
|
||||
$subscription = Subscription::where('team_id', $team_id)->where('lemon_order_id', $order_id)->first();
|
||||
if ($subscription) {
|
||||
send_internal_notification('Subscription cancelled or paused: ' . $subscription_id . ' for team ' . $team_id . ' with status ' . $status);
|
||||
send_internal_notification("LemonSqueezy Event (`$event`): " . $subscription_id . ' for team ' . $team_id . ' with status ' . $status);
|
||||
$subscription->update([
|
||||
'lemon_status' => $status,
|
||||
'lemon_trial_ends_at' => $trial_ends_at,
|
||||
|
Loading…
Reference in New Issue
Block a user