From ccf38ef6f961072bc01245efd246c2229cb0a112 Mon Sep 17 00:00:00 2001
From: jon brookes 
In FlowiseAI, applications based on the JavaScript fork of LangChain are modeled in a 'no/low-code' environment. If you are coming from a closed source world, yet trying to implement devops principles this may fill you with fear, dread and uncertainty. FlowiseAI offers the advantage of using plain-text JSON files to represent each workflow. These files are easy to understand, open, and readily backup-able, unlike opaque proprietary binary formats\nThe data used at runtime and other component prerequisites like credentials are stored in the FlowiseAI data volume, which looks like this
\nbash\nMode LastWriteTime ..... 8ZS1C0ZBB.webp",
+ "created_at": "2024-12-17 11:24:59",
+ "updated_at": "2024-12-17 12:53:54",
+ "category_id": 1,
+ "blog_date": "2024-02-26 00:00",
+ "is_featured": 0,
+ "published": 1
+ },
+
+ */
+
+ $filePath = '/home/user/projects/laravel/12/media_library/boring-astro-static/imported_database/blogs.json';
+
+ if (!file_exists($filePath)) {
+ $this->error("File not found: $filePath");
+ return 1;
+ }
+
+ $jsonContent = file_get_contents($filePath);
+ $blogs = json_decode($jsonContent, true);
+
+ if (!$blogs) {
+ $this->error("Could not parse JSON file: $filePath");
+ return 1;
+ }
+
+ foreach ($blogs as $blog) {
+ // Only process the blog with ID 51
+ if (($blog['id'] ?? null) !== 51) {
+ continue;
+ }
+
+ $slug = $blog['slug'] ?? null;
+ $this->info("Processing blog ID: {$blog['id']} with slug: {$slug}");
+ // Check if the entry already exists
+ $existingEntry = Entry::where('slug', $slug)->first();
+
+ if ($existingEntry) {
+ // Update existing entry with cleaned content
+ $existingEntry->update([
+ 'content' => $this->cleanHtmlForFilament($blog['content'] ?? ''),
+ 'description' => $this->extractPlainTextFromHtml($blog['content'] ?? ''),
+ ]);
+ $this->info("Updated content for: {$existingEntry->title}");
+ } else {
+ // Create new entry
+ Entry::create([
+ 'title' => $blog['title'] ?? null,
+ 'slug' => $slug,
+ 'description' => $this->extractPlainTextFromHtml($blog['content'] ?? ''),
+ 'is_published' => $blog['published'] ?? false,
+ 'is_featured' => $blog['is_featured'] ?? false,
+ 'published_at' => $blog['blog_date'] ?? null,
+ 'content' => $this->cleanHtmlForFilament($blog['content'] ?? ''),
+ 'category_id' => 1, // Default category
+ ]);
+ $this->info("Created new entry: " . ($blog['title'] ?? 'Untitled'));
+ }
+ }
+
+ $this->info('Blogs imported successfully.');
+ }
+
+ /**
+ * Extract plain text from HTML for description field
+ */
+ private function extractPlainTextFromHtml(string $html): string
+ {
+ if (empty($html)) {
+ return '';
+ }
+
+ // Decode HTML entities and strip tags
+ $text = html_entity_decode(strip_tags($html));
+
+ // Clean up whitespace
+ $text = preg_replace('/\s+/', ' ', $text);
+
+ // Limit to reasonable length for description
+ return trim(substr($text, 0, 500));
+ }
+
+ /**
+ * Clean HTML content for Filament rich editor
+ */
+ private function cleanHtmlForFilament(string $html): string
+ {
+ if (empty($html)) {
+ return '';
+ }
+
+ // Convert escaped newlines to actual newlines
+ $html = str_replace(['\\n', '\\r\\n', '\\r'], "\n", $html);
+
+ // Decode HTML entities
+ $html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+
+ // Clean up excessive whitespace but preserve paragraph structure
+ $html = preg_replace('/\s*\n\s*/', ' ', $html);
+ $html = preg_replace('/[ \t]+/', ' ', $html);
+
+ // Ensure paragraphs have proper spacing
+ $html = str_replace('
', '
' . "\n" . '', $html); + + return trim($html); + } +} diff --git a/app/Console/Commands/ImportImages.php b/app/Console/Commands/ImportImages.php new file mode 100644 index 0000000..7c93d12 --- /dev/null +++ b/app/Console/Commands/ImportImages.php @@ -0,0 +1,61 @@ +option('entry-id'); + $entry = Entry::find($entryId); + + if (!$entry) { + $this->error("Entry with ID {$entryId} not found"); + return; + } + + $files = Storage::disk('public')->files('imported_images'); + + if (empty($files)) { + $this->info('No files found in storage/app/public/imported_images/'); + return; + } + + $this->info("Found " . count($files) . " files to import"); + + foreach ($files as $filePath) { + try { + $fullPath = storage_path('app/public/' . $filePath); + $fileName = pathinfo($fullPath, PATHINFO_BASENAME); + + if (!file_exists($fullPath)) { + $this->error("File not found: {$fullPath}"); + continue; + } + + // Check if already exists + $existingMedia = $entry->getMedia()->where('file_name', $fileName)->first(); + if ($existingMedia) { + $this->info("Skipping existing: {$fileName}"); + continue; + } + + $media = $entry->addMedia($fullPath) + ->toMediaCollection('default'); + + $this->info("Imported: {$fileName}"); + } catch (\Exception $e) { + $this->error("Failed to import {$filePath}: " . $e->getMessage()); + } + } + + $this->info('Import completed'); + } +} diff --git a/app/Filament/Resources/Entries/Tables/EntriesTable.php b/app/Filament/Resources/Entries/Tables/EntriesTable.php index eb89fd4..723c1fd 100644 --- a/app/Filament/Resources/Entries/Tables/EntriesTable.php +++ b/app/Filament/Resources/Entries/Tables/EntriesTable.php @@ -17,18 +17,33 @@ class EntriesTable { return $table ->columns([ + TextColumn::make('id') + ->label('ID') + ->sortable(query: function ($query, $direction) { + $query->orderBy('id', $direction); + }), SpatieMediaLibraryImageColumn::make('featured_image') ->collection('featured-image') + ->label('Image') ->circular() ->stacked() ->limit(3), TextColumn::make('title') - ->searchable(), - TextColumn::make('slug') + ->searchable() + ->sortable(), + TextColumn::make('category.name') + ->label('Category') + ->sortable(query: function ($query, $direction) { + $query->join('categories', 'entries.category_id', '=', 'categories.id') + ->orderBy('categories.name', $direction) + ->select('entries.*'); + }) ->searchable(), IconColumn::make('is_published') + ->label('pub') ->boolean(), IconColumn::make('is_featured') + ->label('feat') ->boolean(), TextColumn::make('published_at') ->date() diff --git a/app/Models/Entry.php b/app/Models/Entry.php index 476e4b5..d6d6406 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -32,6 +32,7 @@ class Entry extends Model implements HasMedia, HasRichContent 'content', 'call_to_action_link', 'call_to_action_text', + 'category_id', ]; /**