# frozen_string_literal: true class ConvertHtmlContentToEditorJs < ActiveRecord::Migration[7.1] def up # First, let's ensure we have the converter available in the migration require Panda::CMS::Engine.root.join("app/services/panda/cms/html_to_editor_js_converter") # Check if we have any existing valid EditorJS content existing_editor_js = Panda::CMS::BlockContent.find_each.any? do |block_content| valid_editor_js_content?(block_content.content) end if existing_editor_js Rails.logger.warn "Found existing valid EditorJS content. Skipping migration to prevent data loss." return end Rails.logger.info "Starting conversion of HTML content to EditorJS format..." # Get all block contents that need conversion Panda::CMS::BlockContent.find_each do |block_content| next if block_content.content.blank? begin Rails.logger.info "Converting content for BlockContent ##{block_content.id}" # Convert the content editor_js_content = Panda::CMS::HtmlToEditorJsConverter.convert(block_content.content) # Validate the converted content unless valid_editor_js_content?(editor_js_content) Rails.logger.error "Skipping BlockContent ##{block_content.id}: Conversion resulted in invalid or empty content" next end # Update the record directly to avoid callbacks block_content.update_columns( content: editor_js_content, updated_at: Time.current ) Rails.logger.info "Successfully converted BlockContent ##{block_content.id}" rescue => e Rails.logger.error "Failed to convert BlockContent ##{block_content.id}: #{e.message}" # Continue with the next record instead of failing the entire migration end end Rails.logger.info "Completed conversion to EditorJS format" end def down Rails.logger.warn "This migration cannot be reversed as it would require original HTML content" end private def valid_editor_js_content?(content) return false unless content.is_a?(Hash) return false unless content["blocks"].is_a?(Array) return false if content["blocks"].empty? # Check if there are any non-empty blocks content["blocks"].any? do |block| next false unless block.is_a?(Hash) next false unless block["data"].is_a?(Hash) case block["type"] when "paragraph" block["data"]["text"].present? when "header" block["data"]["text"].present? when "list" block["data"]["items"].present? && block["data"]["items"].any?(&:present?) when "quote" block["data"]["text"].present? else false end end end end