fix: remove lemon + paddle things

This commit is contained in:
Andras Bacsai 2024-06-25 13:54:58 +02:00
parent f557cd0933
commit 3ebb35a5cd
12 changed files with 21 additions and 480 deletions

View File

@ -3,7 +3,6 @@
namespace App\Livewire\Subscription; namespace App\Livewire\Subscription;
use App\Models\Team; use App\Models\Team;
use Illuminate\Support\Facades\Http;
use Livewire\Component; use Livewire\Component;
class Actions extends Component class Actions extends Component
@ -15,70 +14,6 @@ public function mount()
$this->server_limits = Team::serverLimit(); $this->server_limits = Team::serverLimit();
} }
public function cancel()
{
try {
$subscription_id = 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('subscription.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->dispatch('success', 'Subscription cancelled successfully. Reloading in 5s.');
$this->dispatch('reloadWindow', 5000);
}
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function resume()
{
try {
$subscription_id = 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('subscription.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->dispatch('success', 'Subscription resumed successfully. Reloading in 5s.');
$this->dispatch('reloadWindow', 5000);
}
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function stripeCustomerPortal() public function stripeCustomerPortal()
{ {
$session = getStripeCustomerPortalSession(currentTeam()); $session = getStripeCustomerPortalSession(currentTeam());

View File

@ -15,22 +15,7 @@ public function team()
public function type() public function type()
{ {
if (isLemon()) { if (isStripe()) {
$basic = explode(',', config('subscription.lemon_squeezy_basic_plan_ids'));
$pro = explode(',', config('subscription.lemon_squeezy_pro_plan_ids'));
$ultimate = explode(',', config('subscription.lemon_squeezy_ultimate_plan_ids'));
$subscription = $this->lemon_variant_id;
if (in_array($subscription, $basic)) {
return 'basic';
}
if (in_array($subscription, $pro)) {
return 'pro';
}
if (in_array($subscription, $ultimate)) {
return 'ultimate';
}
} elseif (isStripe()) {
if (! $this->stripe_plan_id) { if (! $this->stripe_plan_id) {
return 'zero'; return 'zero';
} }

View File

@ -1,51 +1,8 @@
<?php <?php
use App\Models\Team; use App\Models\Team;
use Illuminate\Support\Carbon;
use Stripe\Stripe; use Stripe\Stripe;
function getSubscriptionLink($type)
{
$checkout_id = config("subscription.lemon_squeezy_checkout_id_$type");
if (! $checkout_id) {
return null;
}
$user_id = auth()->user()->id;
$team_id = currentTeam()->id ?? null;
$email = auth()->user()->email ?? null;
$name = auth()->user()->name ?? null;
$url = "https://store.coollabs.io/checkout/buy/$checkout_id?";
if ($user_id) {
$url .= "&checkout[custom][user_id]={$user_id}";
}
if (isset($team_id)) {
$url .= "&checkout[custom][team_id]={$team_id}";
}
if ($email) {
$url .= "&checkout[email]={$email}";
}
if ($name) {
$url .= "&checkout[name]={$name}";
}
return $url;
}
function getPaymentLink()
{
return currentTeam()->subscription->lemon_update_payment_menthod_url;
}
function getRenewDate()
{
return Carbon::parse(currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
}
function getEndDate()
{
return Carbon::parse(currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
}
function isSubscriptionActive() function isSubscriptionActive()
{ {
if (! isCloud()) { if (! isCloud()) {
@ -60,12 +17,6 @@ function isSubscriptionActive()
if (is_null($subscription)) { if (is_null($subscription)) {
return false; return false;
} }
if (isLemon()) {
return $subscription->lemon_status === 'active';
}
// if (isPaddle()) {
// return $subscription->paddle_status === 'active';
// }
if (isStripe()) { if (isStripe()) {
return $subscription->stripe_invoice_paid === true; return $subscription->stripe_invoice_paid === true;
} }
@ -82,12 +33,6 @@ function isSubscriptionOnGracePeriod()
if (! $subscription) { if (! $subscription) {
return false; return false;
} }
if (isLemon()) {
$is_still_grace_period = $subscription->lemon_ends_at &&
Carbon::parse($subscription->lemon_ends_at) > Carbon::now();
return $is_still_grace_period;
}
if (isStripe()) { if (isStripe()) {
return $subscription->stripe_cancel_at_period_end; return $subscription->stripe_cancel_at_period_end;
} }
@ -98,18 +43,10 @@ function subscriptionProvider()
{ {
return config('subscription.provider'); return config('subscription.provider');
} }
function isLemon()
{
return config('subscription.provider') === 'lemon';
}
function isStripe() function isStripe()
{ {
return config('subscription.provider') === 'stripe'; return config('subscription.provider') === 'stripe';
} }
function isPaddle()
{
return config('subscription.provider') === 'paddle';
}
function getStripeCustomerPortalSession(Team $team) function getStripeCustomerPortalSession(Team $team)
{ {
Stripe::setApiKey(config('subscription.stripe_api_key')); Stripe::setApiKey(config('subscription.stripe_api_key'));

View File

@ -1,7 +1,8 @@
<?php <?php
return [ return [
'provider' => env('SUBSCRIPTION_PROVIDER', null), // stripe, paddle, lemon 'provider' => env('SUBSCRIPTION_PROVIDER', null), // stripe
// Stripe // Stripe
'stripe_api_key' => env('STRIPE_API_KEY', null), 'stripe_api_key' => env('STRIPE_API_KEY', null),
'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', null), 'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', null),
@ -22,29 +23,4 @@
'stripe_price_id_dynamic_monthly' => env('STRIPE_PRICE_ID_DYNAMIC_MONTHLY', null), 'stripe_price_id_dynamic_monthly' => env('STRIPE_PRICE_ID_DYNAMIC_MONTHLY', null),
'stripe_price_id_dynamic_yearly' => env('STRIPE_PRICE_ID_DYNAMIC_YEARLY', null), 'stripe_price_id_dynamic_yearly' => env('STRIPE_PRICE_ID_DYNAMIC_YEARLY', null),
// Paddle
'paddle_vendor_id' => env('PADDLE_VENDOR_ID', null),
'paddle_vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE', null),
'paddle_webhook_secret' => env('PADDLE_WEBHOOK_SECRET', null),
'paddle_public_key' => env('PADDLE_PUBLIC_KEY', null),
'paddle_price_id_basic_monthly' => env('PADDLE_PRICE_ID_BASIC_MONTHLY', null),
'paddle_price_id_basic_yearly' => env('PADDLE_PRICE_ID_BASIC_YEARLY', null),
'paddle_price_id_pro_monthly' => env('PADDLE_PRICE_ID_PRO_MONTHLY', null),
'paddle_price_id_pro_yearly' => env('PADDLE_PRICE_ID_PRO_YEARLY', null),
'paddle_price_id_ultimate_monthly' => env('PADDLE_PRICE_ID_ULTIMATE_MONTHLY', null),
'paddle_price_id_ultimate_yearly' => env('PADDLE_PRICE_ID_ULTIMATE_YEARLY', null),
// Lemon
'lemon_squeezy_api_key' => env('LEMON_SQUEEZY_API_KEY', null),
'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET', null),
'lemon_squeezy_checkout_id_basic_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY', null),
'lemon_squeezy_checkout_id_basic_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY', null),
'lemon_squeezy_checkout_id_pro_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY', null),
'lemon_squeezy_checkout_id_pro_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY', null),
'lemon_squeezy_checkout_id_ultimate_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY', null),
'lemon_squeezy_checkout_id_ultimate_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY', null),
'lemon_squeezy_basic_plan_ids' => env('LEMON_SQUEEZY_BASIC_PLAN_IDS', ''),
'lemon_squeezy_pro_plan_ids' => env('LEMON_SQUEEZY_PRO_PLAN_IDS', ''),
'lemon_squeezy_ultimate_plan_ids' => env('LEMON_SQUEEZY_ULTIMATE_PLAN_IDS', ''),
]; ];

View File

@ -69,27 +69,6 @@ services:
- STRIPE_PRICE_ID_ULTIMATE_MONTHLY_OLD - STRIPE_PRICE_ID_ULTIMATE_MONTHLY_OLD
- STRIPE_PRICE_ID_ULTIMATE_YEARLY_OLD - STRIPE_PRICE_ID_ULTIMATE_YEARLY_OLD
- STRIPE_EXCLUDED_PLANS - STRIPE_EXCLUDED_PLANS
- PADDLE_VENDOR_ID
- PADDLE_WEBHOOK_SECRET
- PADDLE_VENDOR_AUTH_CODE
- PADDLE_PUBLIC_KEY
- PADDLE_PRICE_ID_BASIC_MONTHLY
- PADDLE_PRICE_ID_BASIC_YEARLY
- PADDLE_PRICE_ID_PRO_MONTHLY
- PADDLE_PRICE_ID_PRO_YEARLY
- PADDLE_PRICE_ID_ULTIMATE_MONTHLY
- PADDLE_PRICE_ID_ULTIMATE_YEARLY
- LEMON_SQUEEZY_API_KEY
- LEMON_SQUEEZY_WEBHOOK_SECRET
- LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY
- LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY
- LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY
- LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY
- LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY
- LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY
- LEMON_SQUEEZY_BASIC_PLAN_IDS
- LEMON_SQUEEZY_PRO_PLAN_IDS
- LEMON_SQUEEZY_ULTIMATE_PLAN_IDS
ports: ports:
- "${APP_PORT:-8000}:80" - "${APP_PORT:-8000}:80"
expose: expose:

View File

@ -1,80 +0,0 @@
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
x-on:click="subscribe('basic-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
x-on:click="subscribe('basic-yearly')"> Subscribe
</x-forms.button>
</x-slot:basic>
<x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
x-on:click="subscribe('pro-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
x-on:click="subscribe('pro-yearly')"> Subscribe
</x-forms.button>
</x-slot:pro>
<x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
x-on:click="subscribe('ultimate-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
x-on:click="subscribe('ultimate-yearly')"> Subscribe
</x-forms.button>
</x-slot:ultimate>
<x-slot:other>
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
<script type="text/javascript">
Paddle.Environment.set("{{ isDev() ? 'sandbox' : 'production' }}");
Paddle.Setup({
seller: {{ config('subscription.paddle_vendor_id') }},
checkout: {
settings: {
displayMode: "overlay",
theme: "light",
}
}
});
function subscribe(type) {
let priceId = null
switch (type) {
case 'basic-monthly':
priceId = "{{ config('subscription.paddle_price_id_basic_monthly') }}"
break;
case 'basic-yearly':
priceId = "{{ config('subscription.paddle_price_id_basic_yearly') }}"
break;
case 'pro-monthly':
priceId = "{{ config('subscription.paddle_price_id_pro_monthly') }}"
break;
case 'pro-yearly':
priceId = "{{ config('subscription.paddle_price_id_pro_yearly') }}"
break;
case 'ultimate-monthly':
priceId = "{{ config('subscription.paddle_price_id_ultimate_monthly') }}"
break;
case 'ultimate-yearly':
priceId = "{{ config('subscription.paddle_price_id_ultimate_yearly') }}"
break;
default:
break;
}
Paddle.Checkout.open({
customer: {
email: '{{ auth()->user()->email }}',
},
customData: {
"team_id": "{{ currentTeam()->id }}",
},
items: [{
priceId,
quantity: 1
}],
});
}
</script>
</x-slot:other>

View File

@ -34,15 +34,16 @@ class="font-bold dark:text-warning">{{ config('constants.limits.trial_period') }
<div> <div>
</div> </div>
</div> </div>
{{-- <div class="p-4 rounded bg-coolgray-400"> <div class="p-4 rounded bg-coolgray-400">
<h2 id="tier-hobby" class="flex items-start gap-4 text-4xl font-bold tracking-tight">Unlimited Trial <h2 id="tier-hobby" class="flex items-start gap-4 text-4xl font-bold tracking-tight">Unlimited Trial
<x-forms.button><a class="font-bold dark:text-white hover:no-underline" <x-forms.button><a class="font-bold dark:text-white hover:no-underline"
href="https://github.com/coollabsio/coolify">Get Started</a></x-forms.button> href="https://github.com/coollabsio/coolify">Get Started</a></x-forms.button>
</h2> </h2>
<p class="mt-4 text-sm leading-6">Start self-hosting <span class="dark:text-warning">without limits</span> with <p class="mt-4 text-sm leading-6">Start self-hosting <span class="dark:text-warning">without limits</span>
with
our our
OSS version. Same features as the paid version, but you have to manage by yourself.</p> OSS version. Same features as the paid version, but you have to manage by yourself.</p>
</div> --}} </div>
<div class="flow-root mt-12"> <div class="flow-root mt-12">
<div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a <div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
@ -78,8 +79,8 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-
</p> </p>
<ul role="list" class="space-y-3 text-sm leading-6 "> <ul role="list" class="space-y-3 text-sm leading-6 ">
<li class="flex"> <li class="flex">
<svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20" fill="currentColor" <svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20"
aria-hidden="true"> fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" <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.775 0 001.137-.089l4-5.5z" 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.775 0 001.137-.089l4-5.5z"
clip-rule="evenodd" /> clip-rule="evenodd" />
@ -141,13 +142,14 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-
{{ $pro }} {{ $pro }}
@endisset @endisset
@endif @endif
<p class="h-20 mt-10 text-sm leading-6 dark:text-white">Expand your business or set up your own hosting <p class="h-20 mt-10 text-sm leading-6 dark:text-white">Expand your business or set up your own
hosting
environment. environment.
</p> </p>
<ul role="list" class="mt-6 space-y-3 text-sm leading-6 "> <ul role="list" class="mt-6 space-y-3 text-sm leading-6 ">
<li class="flex "> <li class="flex ">
<svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20" fill="currentColor" <svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20"
aria-hidden="true"> fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" <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" 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" /> clip-rule="evenodd" />
@ -213,8 +215,8 @@ class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-
single location.</p> single location.</p>
<ul role="list" class="mt-6 space-y-3 text-sm leading-6 "> <ul role="list" class="mt-6 space-y-3 text-sm leading-6 ">
<li class="flex "> <li class="flex ">
<svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20" fill="currentColor" <svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20"
aria-hidden="true"> fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" <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" 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" /> clip-rule="evenodd" />

View File

@ -2,8 +2,7 @@
@if (subscriptionProvider() === 'stripe') @if (subscriptionProvider() === 'stripe')
<div class="pt-4"> <div class="pt-4">
<h2>Your current plan</h2> <h2>Your current plan</h2>
<div class="pb-4">Tier: <strong <div class="pb-4">Tier: <strong class="dark:text-warning">
class="dark:text-warning">
@if (data_get(currentTeam(), 'subscription')->type() == 'dynamic') @if (data_get(currentTeam(), 'subscription')->type() == 'dynamic')
Pay-as-you-go Pay-as-you-go
@else @else
@ -50,35 +49,4 @@ class="dark:text-warning">
target="_blank">contact us.</a> target="_blank">contact us.</a>
</div> </div>
@endif @endif
{{-- @if (subscriptionProvider() === 'lemon')
<div>Status: {{ currentTeam()->subscription->lemon_status }}</div>
<div>Type: {{ currentTeam()->subscription->lemon_variant_name }}</div>
@if (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="underline dark:text-white" href="{{ config('coolify.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 (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="dark:text-white hover:no-underline" href="{{ getPaymentLink() }}">Update Payment
Details</a>
</x-forms.button>
<a class="dark:text-white hover:no-underline"
href="https://app.lemonsqueezy.com/my-orders"><x-forms.button>Manage My
Subscription</x-forms.button></a>
</div>
</div>
@endif --}}
</div> </div>

View File

@ -1,67 +0,0 @@
<x-pricing-plans>
@if (config('subscription.provider') === 'stripe')
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
wire:click="subscribeStripe('basic-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
wire:click="subscribeStripe('basic-yearly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:basic>
<x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="subscribeStripe('pro-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="subscribeStripe('pro-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:pro>
<x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
wire:click="subscribeStripe('ultimate-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
wire:click="subscribeStripe('ultimate-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:ultimate>
@endif
@if (config('subscription.provider') === 'paddle')
<x-paddle />
@endif
@if (config('subscription.provider') === 'lemon')
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-yearly')"> Subscribe
</x-forms.button>
</x-slot:basic>
<x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('pro-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="getSubscriptionLink('pro-yearly')"> Subscribe
</x-forms.button>
</x-slot:pro>
<x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-yearly')"> Subscribe
</x-forms.button>
</x-slot:ultimate>
@endif
</x-pricing-plans>

View File

@ -25,7 +25,7 @@
<div>This is the default team. You can't delete it.</div> <div>This is the default team. You can't delete it.</div>
@elseif(auth()->user()->teams()->get()->count() === 1 || auth()->user()->currentTeam()->personal_team) @elseif(auth()->user()->teams()->get()->count() === 1 || auth()->user()->currentTeam()->personal_team)
<div>You can't delete your last / personal team.</div> <div>You can't delete your last / personal team.</div>
@elseif(currentTeam()->subscription && currentTeam()->subscription?->lemon_status !== 'cancelled') @elseif(currentTeam()->subscription)
<div>Please cancel your subscription <a class="underline dark:text-white" <div>Please cancel your subscription <a class="underline dark:text-white"
href="{{ route('subscription.show') }}">here</a> before delete this team.</div> href="{{ route('subscription.show') }}">here</a> before delete this team.</div>
@else @else

View File

@ -1,62 +0,0 @@
<?php
use App\Actions\CoolifyTask\RunRemoteProcess;
use App\Actions\CoolifyTask\TidyOutput;
use App\Models\Server;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
uses(DatabaseMigrations::class);
beforeEach(function () {
$this->seed(DatabaseSeeder::class);
});
it('starts a docker container correctly', function () {
test()->actingAs(User::factory([
'uuid' => Str::uuid(),
'email' => Str::uuid() . '@example.com',
])->create());
$coolifyNamePrefix = 'coolify_test_';
$format = '{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}"}';
$areThereCoolifyTestContainers = "docker ps --filter=\"name={$coolifyNamePrefix}*\" --format '{$format}' ";
// Generate a known name
$containerName = 'coolify_test_' . now()->format('Ymd_his');
$host = Server::where('name', 'testing-local-docker-container')->first();
remote_process([
"docker rm -f $(docker ps --filter='name={$coolifyNamePrefix}*' -aq) > /dev/null 2>&1"
], $host);
// Assert there's no containers start with coolify_test_*
$activity = remote_process([$areThereCoolifyTestContainers], $host);
$tidyOutput = RunRemoteProcess::decodeOutput($activity);
$containers = format_docker_command_output_to_json($tidyOutput);
expect($containers)->toBeEmpty();
// start a container nginx -d --name = $containerName
$activity = remote_process(["docker run -d --rm --name {$containerName} nginx"], $host);
expect($activity->getExtraProperty('exitCode'))->toBe(0);
// docker ps name = $container
$activity = remote_process([$areThereCoolifyTestContainers], $host);
$tidyOutput = RunRemoteProcess::decodeOutput($activity);
$containers = format_docker_command_output_to_json($tidyOutput);
expect($containers->where('Names', $containerName)->count())->toBe(1);
// Stop testing containers
$activity = remote_process([
"docker ps --filter='name={$coolifyNamePrefix}*' -aq && " .
"docker rm -f $(docker ps --filter='name={$coolifyNamePrefix}*' -aq)"
], $host);
expect($activity->getExtraProperty('exitCode'))->toBe(0);
});

View File

@ -1,32 +0,0 @@
<?php
use App\Actions\CoolifyTask\RunRemoteProcess;
use App\Models\Server;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
uses(DatabaseMigrations::class);
beforeEach(function () {
$this->seed(DatabaseSeeder::class);
});
it('outputs correctly', function () {
$host = Server::where('name', 'testing-local-docker-container')->first();
$activity = remote_process([
'pwd',
'x=1; while [ $x -le 3 ]; do sleep 0.1 && echo "Welcome $x times" $(( x++ )); done',
], $host);
$tidyOutput = RunRemoteProcess::decodeOutput($activity);
expect($tidyOutput)
->toContain('Welcome 1 times')
->toContain('Welcome 3 times')
->not()->toBeJson();
});