From 6a897600f5f9490f46dea476f937e5cbe5e4800b Mon Sep 17 00:00:00 2001 From: Sebastian Fix Date: Tue, 24 Jun 2025 07:18:20 +0200 Subject: [PATCH 1/2] First draft codebar Solutions AG v2 --- app/Actions/ViewDataAction.php | 20 ++++ .../OpenSource/OpenSoruceShowController.php | 2 +- .../OpenSource/OpenSourceIndexController.php | 6 +- .../TechnologiesIndexController.php | 6 +- app/Models/OpenSource.php | 28 +++++ app/Models/Technology.php | 27 +++++ database/factories/OpenSourceFactory.php | 23 ++++ database/factories/TechnologyFactory.php | 23 ++++ ...06_24_063710_create_open_sources_table.php | 40 +++++++ ...06_24_063716_create_technologies_table.php | 39 +++++++ database/seeders/Codebar/NewsTableSeeder.php | 101 ++++++++++++++++++ .../seeders/Codebar/OpenSourceTableSeeder.php | 76 +++++++++++++ .../Codebar/TechnologiesTableSeeder.php | 74 +++++++++++++ database/seeders/CodebarSeeder.php | 6 +- .../views/app/open-source/index.blade.php | 7 +- .../views/app/technologies/index.blade.php | 7 +- .../views/components/list-card.blade.php | 2 +- .../views/layouts/_logos/_codebar.blade.php | 2 +- 18 files changed, 472 insertions(+), 17 deletions(-) create mode 100644 app/Models/OpenSource.php create mode 100644 app/Models/Technology.php create mode 100644 database/factories/OpenSourceFactory.php create mode 100644 database/factories/TechnologyFactory.php create mode 100644 database/migrations/2025_06_24_063710_create_open_sources_table.php create mode 100644 database/migrations/2025_06_24_063716_create_technologies_table.php create mode 100644 database/seeders/Codebar/NewsTableSeeder.php create mode 100644 database/seeders/Codebar/OpenSourceTableSeeder.php create mode 100644 database/seeders/Codebar/TechnologiesTableSeeder.php diff --git a/app/Actions/ViewDataAction.php b/app/Actions/ViewDataAction.php index c062c1a..ab1abb6 100644 --- a/app/Actions/ViewDataAction.php +++ b/app/Actions/ViewDataAction.php @@ -7,8 +7,10 @@ use App\Models\Configuration; use App\Models\Contact; use App\Models\News; +use App\Models\OpenSource; use App\Models\Product; use App\Models\Service; +use App\Models\Technology; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; @@ -51,6 +53,24 @@ public function news(string $locale): Collection }); } + public function technologies(string $locale): Collection + { + $key = Str::slug("technologies_published_{$locale}"); + + return Cache::rememberForever($key, function () use ($locale) { + return Technology::where('locale', $locale)->where('published', true)->orderBy('order')->get(); + }); + } + + public function openSource(string $locale): Collection + { + $key = Str::slug("open_source_published_{$locale}"); + + return Cache::rememberForever($key, function () use ($locale) { + return OpenSource::where('locale', $locale)->where('published', true)->orderByDesc('downloads')->get(); + }); + } + public function contacts(string $locale): object { $key = Str::slug("contacts_published_{$locale}"); diff --git a/app/Http/Controllers/OpenSource/OpenSoruceShowController.php b/app/Http/Controllers/OpenSource/OpenSoruceShowController.php index 1dda047..c8a5af7 100644 --- a/app/Http/Controllers/OpenSource/OpenSoruceShowController.php +++ b/app/Http/Controllers/OpenSource/OpenSoruceShowController.php @@ -15,7 +15,7 @@ class OpenSoruceShowController extends Controller */ public function __invoke(string $locale, Product $product): View { - return view('app.products.show')->with([ + return view('app.open-source.show')->with([ 'page' => (new PageAction(locale: $locale))->product(product: $product), 'name' => $product->name, 'teaser' => $product->teaser, diff --git a/app/Http/Controllers/OpenSource/OpenSourceIndexController.php b/app/Http/Controllers/OpenSource/OpenSourceIndexController.php index a34a761..2d54c9b 100644 --- a/app/Http/Controllers/OpenSource/OpenSourceIndexController.php +++ b/app/Http/Controllers/OpenSource/OpenSourceIndexController.php @@ -16,9 +16,9 @@ public function __invoke(): View { $locale = app()->getLocale(); - return view('app.products.index')->with([ - 'page' => (new PageAction(locale: null, routeName: 'products.index'))->default(), - 'products' => (new ViewDataAction)->products($locale), + return view('app.open-source.index')->with([ + 'page' => (new PageAction(locale: null, routeName: 'open-source.index'))->default(), + 'openSource' => (new ViewDataAction)->openSource($locale), ]); } } diff --git a/app/Http/Controllers/Technologies/TechnologiesIndexController.php b/app/Http/Controllers/Technologies/TechnologiesIndexController.php index ed76d36..8239d88 100644 --- a/app/Http/Controllers/Technologies/TechnologiesIndexController.php +++ b/app/Http/Controllers/Technologies/TechnologiesIndexController.php @@ -16,9 +16,9 @@ public function __invoke(): View { $locale = app()->getLocale(); - return view('app.products.index')->with([ - 'page' => (new PageAction(locale: null, routeName: 'products.index'))->default(), - 'products' => (new ViewDataAction)->products($locale), + return view('app.technologies.index')->with([ + 'page' => (new PageAction(locale: null, routeName: 'technologies.index'))->default(), + 'technologies' => (new ViewDataAction)->technologies($locale), ]); } } diff --git a/app/Models/OpenSource.php b/app/Models/OpenSource.php new file mode 100644 index 0000000..2e62923 --- /dev/null +++ b/app/Models/OpenSource.php @@ -0,0 +1,28 @@ + 'boolean', + 'locale' => LocaleEnum::class, + 'tags' => 'json', + 'downloads' => 'int', + ]; + + public function getRouteKeyName(): string + { + return 'slug'; + } +} diff --git a/app/Models/Technology.php b/app/Models/Technology.php new file mode 100644 index 0000000..9e14e60 --- /dev/null +++ b/app/Models/Technology.php @@ -0,0 +1,27 @@ + 'boolean', + 'locale' => LocaleEnum::class, + 'tags' => 'json', + ]; + + public function getRouteKeyName(): string + { + return 'slug'; + } +} diff --git a/database/factories/OpenSourceFactory.php b/database/factories/OpenSourceFactory.php new file mode 100644 index 0000000..d213c76 --- /dev/null +++ b/database/factories/OpenSourceFactory.php @@ -0,0 +1,23 @@ + + */ +class OpenSourceFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/factories/TechnologyFactory.php b/database/factories/TechnologyFactory.php new file mode 100644 index 0000000..e047daf --- /dev/null +++ b/database/factories/TechnologyFactory.php @@ -0,0 +1,23 @@ + + */ +class TechnologyFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2025_06_24_063710_create_open_sources_table.php b/database/migrations/2025_06_24_063710_create_open_sources_table.php new file mode 100644 index 0000000..5e9f4b9 --- /dev/null +++ b/database/migrations/2025_06_24_063710_create_open_sources_table.php @@ -0,0 +1,40 @@ +id(); + $table->boolean('published')->default(false); + $table->string('locale'); + $table->string('title'); + $table->string('slug'); + $table->string('teaser'); + $table->longText('content')->nullable(); + $table->string('image'); + $table->json('tags')->nullable(); + $table->string('link')->nullable(); + $table->integer('downloads')->nullable(); + $table->string('version')->nullable(); + $table->timestamps(); + + $table->unique(['slug', 'locale']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('open_sources'); + } +}; diff --git a/database/migrations/2025_06_24_063716_create_technologies_table.php b/database/migrations/2025_06_24_063716_create_technologies_table.php new file mode 100644 index 0000000..cf5985f --- /dev/null +++ b/database/migrations/2025_06_24_063716_create_technologies_table.php @@ -0,0 +1,39 @@ +id(); + $table->boolean('published')->default(false); + $table->string('locale'); + $table->string('group'); + $table->integer('order'); + $table->string('title'); + $table->string('slug'); + $table->string('teaser'); + $table->longText('content')->nullable(); + $table->string('image'); + $table->json('tags')->nullable(); + $table->string('link')->nullable(); + $table->timestamps(); + $table->unique(['slug', 'locale']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('technologies'); + } +}; diff --git a/database/seeders/Codebar/NewsTableSeeder.php b/database/seeders/Codebar/NewsTableSeeder.php new file mode 100644 index 0000000..38ec9c2 --- /dev/null +++ b/database/seeders/Codebar/NewsTableSeeder.php @@ -0,0 +1,101 @@ +seed( + publishedAt: Carbon::parse('2025-04-06'), + author: 'Sebastian Bürgin-Fix', + localizedData: [ + 'de_CH' => [ + 'title' => 'Hello World! codebar stellt sich vor.', + 'slug' => 'dhello-world-codebar-stellt-sich-vor', + 'teaser' => 'Computerprogramme werden vielfach in fernen Ländern entwickelt, nicht aber bei codebar. Hier gibt es «Software made in Basel». Wir haben Sebastian Fix, den Geschäftsführer dieses Start-ups, nach der Idee dahinter gefragt.', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => file_get_contents(database_path('files/news/de_CH/20250406_docuware_712.md')), + 'tags' => ['DMS/ECM', 'DocuWare'], + ], + 'en_CH' => [ + 'title' => 'DocuWare 7.12 is here', + 'slug' => 'docuware-7-12-is-here', + 'teaser' => 'More automation, more insights, more efficiency', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => file_get_contents(database_path('files/news/en_CH/20250406_docuware_712.md')), + 'tags' => ['DMS/ECM', 'DocuWare'], + + ], + ] + ); + + $this->seed( + publishedAt: Carbon::parse('2025-04-06'), + author: 'Sebastian Bürgin-Fix', + localizedData: [ + 'de_CH' => [ + 'title' => 'DocuWare und codebar Solutions AG: Zwei Partner, eine Mission', + 'slug' => 'docu-ware-cloud-partner', + 'teaser' => 'Die codebar Solutions AG ist seit Februar 2023 offizieller Partner der Dokumenten-Management-Lösung (DMS) DocuWare Cloud. Dadurch haben unsere Kund*innen ab sofort ein Tool an der Hand, welches ihnen helfen wird, die Digitalisierung im eigenen Unternehmen voranzutreiben.', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => file_get_contents(database_path('files/news/de_CH/20250406_docuware_712.md')), + 'tags' => ['DMS/ECM', 'DocuWare'], + ], + 'en_CH' => [ + 'title' => 'DocuWare 7.12 is here', + 'slug' => 'docuware-7-12-is-here', + 'teaser' => 'More automation, more insights, more efficiency', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => file_get_contents(database_path('files/news/en_CH/20250406_docuware_712.md')), + 'tags' => ['DMS/ECM', 'DocuWare'], + + ], + ] + ); + + } + + private function seed(Carbon $publishedAt, string $author, array $localizedData): void + { + $entries = collect($localizedData)->map(function ($data, $locale) use ($author, $publishedAt) { + $slug = Str::slug(Arr::get($data, 'slug'), '-', $locale); + + return News::updateOrCreate( + [ + 'locale' => $locale, + 'slug' => $slug, + ], + [ + 'author' => $author, + 'published_at' => $publishedAt, + 'title' => Arr::get($data, 'title'), + 'teaser' => Arr::get($data, 'teaser'), + 'image' => Arr::get($data, 'image'), + 'tags' => Arr::get($data, 'tags', []), + 'content' => Arr::get($data, 'content'), + ] + ); + }); + + $entries->each(function (News $entry) use ($entries) { + $entries->each(function (News $reference) use ($entry) { + $entry->references()->updateOrCreate([ + 'reference_type' => get_class($reference), + 'reference_id' => $reference->id, + 'reference_locale' => $reference->locale, + ]); + }); + }); + } +} diff --git a/database/seeders/Codebar/OpenSourceTableSeeder.php b/database/seeders/Codebar/OpenSourceTableSeeder.php new file mode 100644 index 0000000..504f340 --- /dev/null +++ b/database/seeders/Codebar/OpenSourceTableSeeder.php @@ -0,0 +1,76 @@ +seed( + sharedSlug: 'laravel-zendesk', + localizedData: [ + 'de_CH' => [ + 'title' => 'Laravel Zendesk', + 'teaser' => 'Nahtlose Integration von Zendesk-Supportfunktionen in deine Laravel-Anwendung.', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => null, + 'tags' => ['Laravel', 'Zendesk'], + ], + 'en_CH' => [ + 'title' => 'Laravel Zendesk', + 'teaser' => 'Seamless integration of Zendesk support features into your Laravel application.', + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + 'content' => null, + 'tags' => ['Laravel', 'Zendesk'], + ], + ], + link: 'https://github.com/codebar-ag/laravel-zendesk', + downloads: 684, + version: 'v12.0.1', + ); + + } + + private function seed(string $sharedSlug, array $localizedData, string $link, int $downloads, string $version): void + { + $entries = collect($localizedData)->map(function ($data, $locale) use ($sharedSlug, $link, $downloads) { + $slug = Str::slug($sharedSlug, '-', $locale); + + return OpenSource::updateOrCreate( + [ + 'locale' => $locale, + 'slug' => $slug, + ], + [ + 'published' => true, + 'title' => Arr::get($data, 'title'), + 'teaser' => Arr::get($data, 'teaser'), + 'image' => Arr::get($data, 'image'), + 'tags' => Arr::get($data, 'tags', []), + 'content' => Arr::get($data, 'content'), + 'link' => $link, + 'downloads' => $downloads, + 'version' => $downloads, + ] + ); + }); + + $entries->each(function (OpenSource $entry) use ($entries) { + $entries->each(function (OpenSource $reference) use ($entry) { + $entry->references()->updateOrCreate([ + 'reference_type' => get_class($reference), + 'reference_id' => $reference->id, + 'reference_locale' => $reference->locale, + ]); + }); + }); + } +} diff --git a/database/seeders/Codebar/TechnologiesTableSeeder.php b/database/seeders/Codebar/TechnologiesTableSeeder.php new file mode 100644 index 0000000..783bfe0 --- /dev/null +++ b/database/seeders/Codebar/TechnologiesTableSeeder.php @@ -0,0 +1,74 @@ +seed( + order: 1, + sharedSlug: 'laravel-framework', + group: 'Backend', + localizedData: [ + LocaleEnum::DE->value => [ + 'title' => 'Laravel', + 'teaser' => '', + 'tags' => ['PHP'], + 'content' => null, + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + ], + LocaleEnum::EN->value => [ + 'title' => 'Laravel', + 'teaser' => '', + 'tags' => ['PHP'], + 'content' => null, + 'image' => 'https://res.cloudinary.com/codebar/image/upload/c_scale,dpr_2.0,f_auto,q_auto,w_1200/www-paperflakes-ch/seo/seo_paperflakes.webp', + ], + ], + link: 'https://laravel.com/', + ); + + } + + private function seed(int $order, string $sharedSlug, string $group, array $localizedData, string $link): void + { + $entries = collect($localizedData)->map(function ($data, $locale) use ($sharedSlug, $order, $group, $link) { + $slug = Str::slug($sharedSlug, '-', $locale); + + return Technology::updateOrCreate( + [ + 'locale' => $locale, + 'slug' => $slug, + ], + [ + 'published' => true, + 'order' => $order, + 'group' => $group, + 'title' => Arr::get($data, 'title'), + 'teaser' => Arr::get($data, 'teaser'), + 'tags' => Arr::get($data, 'tags', []), + 'content' => Arr::get($data, 'content'), + 'image' => Arr::get($data, 'image'), + 'link' => $link, + ] + ); + }); + + $entries->each(function (Technology $entry) use ($entries) { + $entries->each(function (Technology $reference) use ($entry) { + $entry->references()->updateOrCreate([ + 'reference_type' => get_class($reference), + 'reference_id' => $reference->id, + 'reference_locale' => $reference->locale, + ]); + }); + }); + } +} diff --git a/database/seeders/CodebarSeeder.php b/database/seeders/CodebarSeeder.php index 00ed26b..69e2fb3 100644 --- a/database/seeders/CodebarSeeder.php +++ b/database/seeders/CodebarSeeder.php @@ -4,12 +4,12 @@ use Database\Seeders\Codebar\ConfigurationsTableSeeder; use Database\Seeders\Codebar\ContactsTableSeeder; +use Database\Seeders\Codebar\OpenSourceTableSeeder; +use Database\Seeders\Codebar\TechnologiesTableSeeder; use Illuminate\Cache\Console\ClearCommand; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Artisan; -// use Illuminate\Database\Console\Seeds\WithoutModelEvents; - class CodebarSeeder extends Seeder { /** @@ -19,6 +19,8 @@ public function run(): void { $this->call(ConfigurationsTableSeeder::class); $this->call(ContactsTableSeeder::class); + $this->call(OpenSourceTableSeeder::class); + $this->call(TechnologiesTableSeeder::class); if (app()->isLocal()) { Artisan::call(ClearCommand::class); diff --git a/resources/views/app/open-source/index.blade.php b/resources/views/app/open-source/index.blade.php index 7451c06..255d7c3 100644 --- a/resources/views/app/open-source/index.blade.php +++ b/resources/views/app/open-source/index.blade.php @@ -4,10 +4,11 @@ @foreach($openSource as $entry) + :tags="$entry->tags" + target="_blank"/> @endforeach diff --git a/resources/views/app/technologies/index.blade.php b/resources/views/app/technologies/index.blade.php index 1e00fd6..c016400 100644 --- a/resources/views/app/technologies/index.blade.php +++ b/resources/views/app/technologies/index.blade.php @@ -4,10 +4,11 @@ @foreach($technologies as $entry) + :tags="$entry->tags" + target="_blank"/> @endforeach diff --git a/resources/views/components/list-card.blade.php b/resources/views/components/list-card.blade.php index 9facdf8..b5ba77e 100644 --- a/resources/views/components/list-card.blade.php +++ b/resources/views/components/list-card.blade.php @@ -14,7 +14,7 @@ class="group block p-4 transition hover:bg-gray-50/50 hover:shadow-sm rounded mi @endphp @if(!empty($tags) && $tags->count()) -