diff --git a/.github/workflows/coolify-helper.yml b/.github/workflows/coolify-helper.yml index fd4be2f11..a9e8a5dd0 100644 --- a/.github/workflows/coolify-helper.yml +++ b/.github/workflows/coolify-helper.yml @@ -98,3 +98,4 @@ jobs: if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} + diff --git a/app/Console/Commands/ServicesGenerate.php b/app/Console/Commands/ServicesGenerate.php index de64afefa..da04cefce 100644 --- a/app/Console/Commands/ServicesGenerate.php +++ b/app/Console/Commands/ServicesGenerate.php @@ -78,7 +78,7 @@ class ServicesGenerate extends Command if ($logo->count() > 0) { $logo = str($logo[0])->after('# logo:')->trim()->value(); } else { - $logo = 'svgs/unknown.svg'; + $logo = 'svgs/coolify.png'; } $minversion = collect(preg_grep('/^# minversion:/', explode("\n", $content)))->values(); if ($minversion->count() > 0) { diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 3c5f3901b..7f8247597 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -49,11 +49,8 @@ class Select extends Component public ?string $existingPostgresqlUrl = null; - public ?string $search = null; - protected $queryString = [ 'server_id', - 'search', ]; public function mount() @@ -90,40 +87,119 @@ class Select extends Component // } // } - public function updatedSearch() + public function loadServices() { - $this->loadServices(); - } + $services = get_service_templates(true); + $services = collect($services)->map(function ($service, $key) { + return [ + 'name' => str($key)->headline(), + 'logo' => asset(data_get($service, 'logo', 'svgs/coolify.png')), + ] + (array) $service; + })->all(); + $gitBasedApplications = [ + [ + 'id' => 'public', + 'name' => 'Public Repository', + 'description' => 'You can deploy any kind of public repositories from the supported git providers.', + 'logo' => asset('svgs/git.svg'), + ], + [ + 'id' => 'private-gh-app', + 'name' => 'Private Repository (with GitHub App)', + 'description' => 'You can deploy public & private repositories through your GitHub Apps.', + 'logo' => asset('svgs/github.svg'), + ], + [ + 'id' => 'private-deploy-key', + 'name' => 'Private Repository (with Deploy Key)', + 'description' => 'You can deploy private repositories with a deploy key.', + 'logo' => asset('svgs/git.svg'), + ], + ]; + $dockerBasedApplications = [ + [ + 'id' => 'dockerfile', + 'name' => 'Dockerfile', + 'description' => 'You can deploy a simple Dockerfile, without Git.', + 'logo' => asset('svgs/docker.svg'), + ], + [ + 'id' => 'docker-compose-empty', + 'name' => 'Docker Compose Empty', + 'description' => 'You can deploy complex application easily with Docker Compose, without Git.', + 'logo' => asset('svgs/docker.svg'), + ], + [ + 'id' => 'docker-image', + 'name' => 'Docker Image', + 'description' => 'You can deploy an existing Docker Image from any Registry, without Git.', + 'logo' => asset('svgs/docker.svg'), + ], + ]; + $databases = [ + [ + 'id' => 'postgresql', + 'name' => 'PostgreSQL', + 'description' => 'PostgreSQL is an object-relational database known for its robustness, advanced features, and strong standards compliance.', + 'logo' => ' +', + ], + [ + 'id' => 'mysql', + 'name' => 'MySQL', + 'description' => 'MySQL is an open-source relational database management system. ', + 'logo' => '', - public function loadServices(bool $force = false) - { - try { - $this->loadingServices = true; - if (count($this->allServices) > 0 && ! $force) { - if (! $this->search) { - $this->services = $this->allServices; + ], + [ + 'id' => 'mariadb', + 'name' => 'MariaDB', + 'description' => 'MariaDB is a community-developed, commercially supported fork of the MySQL relational database management system, intended to remain free and open-source software under the GNU General Public License.', + 'logo' => '', + ], + [ + 'id' => 'redis', + 'name' => 'Redis', + 'description' => 'Redis is a source-available, in-memory storage, used as a distributed, in-memory key–value database, cache and message broker, with optional durability.', + 'logo' => '', + ], + [ + 'id' => 'keydb', + 'name' => 'KeyDB', + 'description' => 'KeyDB is a database that offers high performance, low latency, and scalability for various data structures and workloads.', + 'logo' => '
', + ], + [ + 'id' => 'dragonfly', + 'name' => 'Dragonfly', + 'description' => 'Dragonfly DB is a drop-in Redis replacement that delivers 25x more throughput and 12x faster snapshotting than Redis.', + 'logo' => '', + ], + [ + 'id' => 'mongodb', + 'name' => 'MongoDB', + 'description' => 'MongoDB is a source-available, cross-platform, document-oriented database program.', + 'logo' => '', + ], + [ + 'id' => 'clickhouse', + 'name' => 'ClickHouse', + 'description' => 'ClickHouse is a column-oriented database that supports real-time analytics, business intelligence, observability, ML and GenAI, and more.', + 'logo' => '', + ], - return; - } - $this->services = $this->allServices->filter(function ($service, $key) { - $tags = collect(data_get($service, 'tags', [])); + ]; - return str_contains(strtolower($key), strtolower($this->search)) || $tags->contains(function ($tag) { - return str_contains(strtolower($tag), strtolower($this->search)); - }); - }); - } else { - $this->search = null; - $this->allServices = get_service_templates($force); - $this->services = $this->allServices->filter(function ($service, $key) { - return str_contains(strtolower($key), strtolower($this->search)); - }); - } - } catch (\Throwable $e) { - return handleError($e, $this); - } finally { - $this->loadingServices = false; - } + return [ + 'services' => $services, + 'gitBasedApplications' => $gitBasedApplications, + 'dockerBasedApplications' => $dockerBasedApplications, + 'databases' => $databases, + ]; } public function instantSave() @@ -141,6 +217,7 @@ class Select extends Component public function setType(string $type) { + $type = str($type)->lower()->slug()->value(); if ($this->loading) { return; } diff --git a/app/Models/Project.php b/app/Models/Project.php index 18481751c..5a9dd964a 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -24,9 +24,11 @@ class Project extends BaseModel { protected $guarded = []; + protected $appends = ['default_environment']; + public static function ownedByCurrentTeam() { - return Project::whereTeamId(currentTeam()->id)->orderBy('name'); + return Project::whereTeamId(currentTeam()->id)->orderByRaw('LOWER(name)'); } protected static function booted() @@ -131,7 +133,7 @@ class Project extends BaseModel return $this->postgresqls()->get()->merge($this->redis()->get())->merge($this->mongodbs()->get())->merge($this->mysqls()->get())->merge($this->mariadbs()->get())->merge($this->keydbs()->get())->merge($this->dragonflies()->get())->merge($this->clickhouses()->get()); } - public function default_environment() + public function getDefaultEnvironmentAttribute() { $default = $this->environments()->where('name', 'production')->first(); if ($default) { diff --git a/app/Models/Service.php b/app/Models/Service.php index dad9a30d9..bcdb74f8c 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -283,9 +283,109 @@ class Service extends BaseModel $fields = collect([]); $applications = $this->applications()->get(); foreach ($applications as $application) { - $image = str($application->image)->before(':')->value(); + $image = str($application->image)->before(':'); + if ($image->isEmpty()) { + continue; + } switch ($image) { - case str($image)?->contains('argilla'): + case $image->contains('label-studio'): + $data = collect([]); + $username = $this->environment_variables()->where('key', 'LABEL_STUDIO_USERNAME')->first(); + $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LABELSTUDIO')->first(); + if ($username) { + $data = $data->merge([ + 'Username' => [ + 'key' => 'LABEL_STUDIO_USERNAME', + 'value' => data_get($username, 'value'), + 'rules' => 'required', + ], + ]); + } + if ($password) { + $data = $data->merge([ + 'Password' => [ + 'key' => 'LABEL_STUDIO_PASSWORD', + 'value' => data_get($password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + $fields->put('Label Studio', $data->toArray()); + break; + case $image->contains('litellm'): + $data = collect([]); + $username = $this->environment_variables()->where('key', 'SERVICE_USER_UI')->first(); + $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UI')->first(); + if ($username) { + $data = $data->merge([ + 'Username' => [ + 'key' => data_get($username, 'key'), + 'value' => data_get($username, 'value'), + 'rules' => 'required', + ], + ]); + } + if ($password) { + $data = $data->merge([ + 'Password' => [ + 'key' => data_get($password, 'key'), + 'value' => data_get($password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + $fields->put('Litellm', $data->toArray()); + break; + case $image->contains('langfuse'): + $data = collect([]); + $email = $this->environment_variables()->where('key', 'LANGFUSE_INIT_USER_EMAIL')->first(); + if ($email) { + $data = $data->merge([ + 'Admin Email' => [ + 'key' => 'LANGFUSE_INIT_USER_EMAIL', + 'value' => data_get($email, 'value'), + 'rules' => 'required|email', + ], + ]); + } + $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LANGFUSE')->first(); + ray('password', $password); + if ($password) { + $data = $data->merge([ + 'Admin Password' => [ + 'key' => 'LANGFUSE_INIT_USER_PASSWORD', + 'value' => data_get($password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + $fields->put('Langfuse', $data->toArray()); + break; + case $image->contains('invoiceninja'): + $data = collect([]); + $email = $this->environment_variables()->where('key', 'IN_USER_EMAIL')->first(); + $data = $data->merge([ + 'Email' => [ + 'key' => 'IN_USER_EMAIL', + 'value' => data_get($email, 'value'), + 'rules' => 'required|email', + ], + ]); + $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_INVOICENINJAUSER')->first(); + $data = $data->merge([ + 'Password' => [ + 'key' => 'IN_PASSWORD', + 'value' => data_get($password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + $fields->put('Invoice Ninja', $data->toArray()); + break; + case $image->contains('argilla'): $data = collect([]); $api_key = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_APIKEY')->first(); $data = $data->merge([ @@ -323,7 +423,7 @@ class Service extends BaseModel ]); $fields->put('Argilla', $data->toArray()); break; - case str($image)?->contains('rabbitmq'): + case $image->contains('rabbitmq'): $data = collect([]); $host_port = $this->environment_variables()->where('key', 'PORT')->first(); $username = $this->environment_variables()->where('key', 'SERVICE_USER_RABBITMQ')->first(); @@ -358,7 +458,7 @@ class Service extends BaseModel } $fields->put('RabbitMQ', $data->toArray()); break; - case str($image)?->contains('tolgee'): + case $image->contains('tolgee'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_TOLGEE')->first(); $data = $data->merge([ @@ -381,7 +481,7 @@ class Service extends BaseModel } $fields->put('Tolgee', $data->toArray()); break; - case str($image)?->contains('logto'): + case $image->contains('logto'): $data = collect([]); $logto_endpoint = $this->environment_variables()->where('key', 'LOGTO_ENDPOINT')->first(); $logto_admin_endpoint = $this->environment_variables()->where('key', 'LOGTO_ADMIN_ENDPOINT')->first(); @@ -405,7 +505,7 @@ class Service extends BaseModel } $fields->put('Logto', $data->toArray()); break; - case str($image)?->contains('unleash-server'): + case $image->contains('unleash-server'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UNLEASH')->first(); $data = $data->merge([ @@ -428,7 +528,7 @@ class Service extends BaseModel } $fields->put('Unleash', $data->toArray()); break; - case str($image)?->contains('grafana'): + case $image->contains('grafana'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GRAFANA')->first(); $data = $data->merge([ @@ -451,7 +551,7 @@ class Service extends BaseModel } $fields->put('Grafana', $data->toArray()); break; - case str($image)?->contains('directus'): + case $image->contains('directus'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); @@ -477,7 +577,7 @@ class Service extends BaseModel } $fields->put('Directus', $data->toArray()); break; - case str($image)?->contains('kong'): + case $image->contains('kong'): $data = collect([]); $dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); $dashboard_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); @@ -501,7 +601,7 @@ class Service extends BaseModel ]); } $fields->put('Supabase', $data->toArray()); - case str($image)?->contains('minio'): + case $image->contains('minio'): $data = collect([]); $console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first(); $s3_api_url = $this->environment_variables()->where('key', 'MINIO_SERVER_URL')->first(); @@ -554,7 +654,7 @@ class Service extends BaseModel $fields->put('MinIO', $data->toArray()); break; - case str($image)?->contains('weblate'): + case $image->contains('weblate'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'WEBLATE_ADMIN_EMAIL')->first(); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_WEBLATE')->first(); @@ -580,7 +680,7 @@ class Service extends BaseModel } $fields->put('Weblate', $data->toArray()); break; - case str($image)?->contains('meilisearch'): + case $image->contains('meilisearch'): $data = collect([]); $SERVICE_PASSWORD_MEILISEARCH = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MEILISEARCH')->first(); if ($SERVICE_PASSWORD_MEILISEARCH) { @@ -594,7 +694,7 @@ class Service extends BaseModel } $fields->put('Meilisearch', $data->toArray()); break; - case str($image)?->contains('ghost'): + case $image->contains('ghost'): $data = collect([]); $MAIL_OPTIONS_AUTH_PASS = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_PASS')->first(); $MAIL_OPTIONS_AUTH_USER = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_USER')->first(); @@ -654,45 +754,8 @@ class Service extends BaseModel $fields->put('Ghost', $data->toArray()); break; - default: - $data = collect([]); - $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); - // Chaskiq - $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); - $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); - if ($admin_user) { - $data = $data->merge([ - 'User' => [ - 'key' => 'SERVICE_USER_ADMIN', - 'value' => data_get($admin_user, 'value', 'admin'), - 'readonly' => true, - 'rules' => 'required', - ], - ]); - } - if ($admin_password) { - $data = $data->merge([ - 'Password' => [ - 'key' => 'SERVICE_PASSWORD_ADMIN', - 'value' => data_get($admin_password, 'value'), - 'rules' => 'required', - 'isPassword' => true, - ], - ]); - } - if ($admin_email) { - $data = $data->merge([ - 'Email' => [ - 'key' => 'ADMIN_EMAIL', - 'value' => data_get($admin_email, 'value'), - 'rules' => 'required|email', - ], - ]); - } - $fields->put('Admin', $data->toArray()); - break; - case str($image)?->contains('vaultwarden'): + case $image->contains('vaultwarden'): $data = collect([]); $DATABASE_URL = $this->environment_variables()->where('key', 'DATABASE_URL')->first(); @@ -758,7 +821,7 @@ class Service extends BaseModel $fields->put('Vaultwarden', $data); break; - case str($image)->contains('gitlab/gitlab'): + case $image->contains('gitlab/gitlab'): $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GITLAB')->first(); $data = collect([]); if ($password) { @@ -782,7 +845,7 @@ class Service extends BaseModel $fields->put('GitLab', $data->toArray()); break; - case str($image)->contains('code-server'): + case $image->contains('code-server'): $data = collect([]); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_64_PASSWORDCODESERVER')->first(); if ($password) { @@ -808,7 +871,7 @@ class Service extends BaseModel } $fields->put('Code Server', $data->toArray()); break; - case str($image)->contains('elestio/strapi'): + case $image->contains('elestio/strapi'): $data = collect([]); $license = $this->environment_variables()->where('key', 'STRAPI_LICENSE')->first(); if ($license) { @@ -831,15 +894,55 @@ class Service extends BaseModel $fields->put('Strapi', $data->toArray()); break; + default: + $data = collect([]); + $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); + // Chaskiq + $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); + $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); + if ($admin_user) { + $data = $data->merge([ + 'User' => [ + 'key' => 'SERVICE_USER_ADMIN', + 'value' => data_get($admin_user, 'value', 'admin'), + 'readonly' => true, + 'rules' => 'required', + ], + ]); + } + if ($admin_password) { + $data = $data->merge([ + 'Password' => [ + 'key' => 'SERVICE_PASSWORD_ADMIN', + 'value' => data_get($admin_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + if ($admin_email) { + $data = $data->merge([ + 'Email' => [ + 'key' => 'ADMIN_EMAIL', + 'value' => data_get($admin_email, 'value'), + 'rules' => 'required|email', + ], + ]); + } + $fields->put('Admin', $data->toArray()); + break; } } $databases = $this->databases()->get(); foreach ($databases as $database) { - $image = str($database->image)->before(':')->value(); + $image = str($database->image)->before(':'); + if ($image->isEmpty()) { + continue; + } switch ($image) { - case str($image)->contains('postgres'): + case $image->contains('postgres'): $userVariables = ['SERVICE_USER_POSTGRES', 'SERVICE_USER_POSTGRESQL']; $passwordVariables = ['SERVICE_PASSWORD_POSTGRES', 'SERVICE_PASSWORD_POSTGRESQL']; $dbNameVariables = ['POSTGRESQL_DATABASE', 'POSTGRES_DB']; @@ -877,7 +980,7 @@ class Service extends BaseModel } $fields->put('PostgreSQL', $data->toArray()); break; - case str($image)->contains('mysql'): + case $image->contains('mysql'): $userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS', 'MYSQL_USER']; $passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS', 'MYSQL_PASSWORD']; $rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT']; @@ -927,7 +1030,7 @@ class Service extends BaseModel } $fields->put('MySQL', $data->toArray()); break; - case str($image)->contains('mariadb'): + case $image->contains('mariadb'): $userVariables = ['SERVICE_USER_MARIADB', 'SERVICE_USER_WORDPRESS', '_APP_DB_USER', 'SERVICE_USER_MYSQL', 'MYSQL_USER']; $passwordVariables = ['SERVICE_PASSWORD_MARIADB', 'SERVICE_PASSWORD_WORDPRESS', '_APP_DB_PASS', 'MYSQL_PASSWORD']; $rootPasswordVariables = ['SERVICE_PASSWORD_MARIADBROOT', 'SERVICE_PASSWORD_ROOT', '_APP_DB_ROOT_PASS', 'MYSQL_ROOT_PASSWORD']; diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 7e902fcdd..397bce029 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -332,8 +332,12 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ if (preg_match('/traefik\.http\.middlewares\.(.*?)(\.|$)/', $item, $matches)) { return $matches[1]; } + if (preg_match('/coolify\.traefik\.middlewares=(.*)/', $item, $matches)) { + return explode(',', $matches[1]); + } return null; - })->filter() + })->flatten() + ->filter() ->unique(); } foreach ($domains as $loop => $domain) { diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 4d78021c4..65fe3322d 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -522,6 +522,11 @@ function sslip(Server $server) function get_service_templates(bool $force = false): Collection { + if (isDev()) { + $services = File::get(base_path('templates/service-templates.json')); + + return collect(json_decode($services))->sortKeys(); + } if ($force) { try { $response = Http::retry(3, 1000)->get(config('constants.services.official')); diff --git a/config/sentry.php b/config/sentry.php index 14f8ff5f1..25cf7e423 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.356', + 'release' => '4.0.0-beta.357', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index b33115d86..ee8ab588e 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ = 0.6" } diff --git a/package.json b/package.json index 3633a7ed1..29f8f1a37 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", "alpinejs": "3.14.0", - "cookie": "^0.6.0", + "cookie": "^0.7.0", "dotenv": "^16.4.5", "ioredis": "5.4.1", "node-pty": "^1.0.0", diff --git a/public/svgs/clickhouse.svg b/public/svgs/clickhouse.svg new file mode 100644 index 000000000..d536536de --- /dev/null +++ b/public/svgs/clickhouse.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/coolify.png b/public/svgs/coolify.png new file mode 100644 index 000000000..fa01fec05 Binary files /dev/null and b/public/svgs/coolify.png differ diff --git a/public/svgs/dozzle.svg b/public/svgs/dozzle.svg new file mode 100644 index 000000000..bf88e8729 --- /dev/null +++ b/public/svgs/dozzle.svg @@ -0,0 +1,10 @@ + + + diff --git a/public/svgs/easyappointments.png b/public/svgs/easyappointments.png new file mode 100644 index 000000000..8f00d3353 Binary files /dev/null and b/public/svgs/easyappointments.png differ diff --git a/public/svgs/getoutline.jpeg b/public/svgs/getoutline.jpeg new file mode 100644 index 000000000..422e402f7 Binary files /dev/null and b/public/svgs/getoutline.jpeg differ diff --git a/public/svgs/labelstudio.png b/public/svgs/labelstudio.png new file mode 100644 index 000000000..afa5160b9 Binary files /dev/null and b/public/svgs/labelstudio.png differ diff --git a/public/svgs/libreoffice.svg b/public/svgs/libreoffice.svg new file mode 100644 index 000000000..227471bef --- /dev/null +++ b/public/svgs/libreoffice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/svgs/nitropage.svg b/public/svgs/nitropage.svg new file mode 100644 index 000000000..67b2df17f --- /dev/null +++ b/public/svgs/nitropage.svg @@ -0,0 +1,8 @@ + diff --git a/public/svgs/ollama.svg b/public/svgs/ollama.svg new file mode 100644 index 000000000..3df9a9fba --- /dev/null +++ b/public/svgs/ollama.svg @@ -0,0 +1,14 @@ + + + diff --git a/public/svgs/organizr.png b/public/svgs/organizr.png new file mode 100644 index 000000000..92541ea72 Binary files /dev/null and b/public/svgs/organizr.png differ diff --git a/public/svgs/postgresql.svg b/public/svgs/postgresql.svg new file mode 100644 index 000000000..1ff223856 --- /dev/null +++ b/public/svgs/postgresql.svg @@ -0,0 +1 @@ + diff --git a/public/svgs/soketi.jpeg b/public/svgs/soketi.jpeg new file mode 100644 index 000000000..00c8d82cd Binary files /dev/null and b/public/svgs/soketi.jpeg differ diff --git a/public/svgs/soketi.png b/public/svgs/soketi.png new file mode 100644 index 000000000..be5a11194 Binary files /dev/null and b/public/svgs/soketi.png differ diff --git a/public/svgs/supertokens.svg b/public/svgs/supertokens.svg new file mode 100644 index 000000000..30b435bd0 --- /dev/null +++ b/public/svgs/supertokens.svg @@ -0,0 +1,17 @@ + diff --git a/public/svgs/tolgee.svg b/public/svgs/tolgee.svg new file mode 100644 index 000000000..0f216e0c6 --- /dev/null +++ b/public/svgs/tolgee.svg @@ -0,0 +1,5 @@ + + diff --git a/resources/views/components/resource-view.blade.php b/resources/views/components/resource-view.blade.php index a01e5ab53..d2c8947ee 100644 --- a/resources/views/components/resource-view.blade.php +++ b/resources/views/components/resource-view.blade.php @@ -2,7 +2,7 @@ 'transition-all duration-150 box-without-bg dark:bg-coolgray-100 bg-white group', 'hover:border-l-coollabs cursor-pointer' => !$upgrade, 'hover:border-l-red-500 cursor-not-allowed' => $upgrade, -]) @if (!$upgrade) wire:click={{ $wire }} @endif> +])>