Thursday, 18 January 2024

Active admin category and sub category in the form

 ActiveAdmin.register BxBlockCatalogue::Catalogue, as: 'Catalogue' do

  menu parent: "Catalogue Management"

  actions :all, :except => [:new]

  permit_params :category_id, :sub_category_id, :brand_id, :name, :sku, :description, :manufacture_date, :length, :breadth, :height, :availability, :stock_qty, :weight, :price, :recommended, :on_sale, :sale_price, :discount, :block_qty, :account_id, :product_number, catalogue_variants_attributes: [:id, :name, :description, :catalogue_variant_color_id, :catalogue_variant_size_id, :price, :stock_qty, :length, :breadth, :height, :block_qty, :sku, :_destroy]

  scope("All Catalogues", default: true) do |scope|

    scope.joins(:account)

  end

  scope("Seller Catalogues") do |scope|

    scope.joins(:account).where(accounts: { role: "seller" })

  end

  scope("Stylist Catalogues") do |scope|

    scope.joins(:account).where(accounts: { role: "stylist" })

  end

  filter :category, as: :searchable_select

  filter :sub_category, as: :searchable_select

  filter :name

  filter :sku

  filter :availability

  filter :stock_qty

  filter :product_number

  filter :account, as: :searchable_select

  filter :category_status, as: :select, collection: -> { BxBlockCategories::Category.all.pluck(:status).uniq.map { |status| [status.titleize, status] } }

  filter :created_at

  filter :updated_at

  index do

    selectable_column

    id_column

    column :category

    column :sub_category

    column :name

    column :sku

    column :description

    column :availability

    column :stock_qty

    column :product_number

    # column :account

    column "Account" do |object|

      if object.account.role == "seller"

        link_to object&.account&.full_name, "/admin/sellers/#{object.account_id}"

      elsif object.account.role == "stylist"

        link_to object&.account&.full_name, "/admin/stylists/#{object.account_id}"

      elsif object.account.role == "driver"

        link_to object&.account&.full_name, "/admin/drivers/#{object.account_id}"

      else

        object.account

      end

    end

    column "Catalogue Status" do |object|

      object&.category&.status&.titleize

    end

    column :created_at

    # column :updated_at

    actions do |cat|

      item "Variants", "/admin/catalogue_variants?q[catalogue_id_eq]=#{cat.id}&commit=Filter&order=id_desc", class: "member_link"

    end  

  end

  show do

    attributes_table do

      row :category

      row :sub_category

      row :name

      row :sku

      row :description

      row :availability

      row :stock_qty

      row :product_number

      row "Account" do |object|

        if object.account.role == "seller"

          link_to object&.account&.full_name, "/admin/sellers/#{object.account_id}"

        elsif object.account.role == "stylist"

          link_to object&.account&.full_name, "/admin/stylists/#{object.account_id}"

        elsif object.account.role == "driver"

          link_to object&.account&.full_name, "/admin/drivers/#{object.account_id}"  

        else

          object.account

        end

      end

      row :created_at

      row :updated_at

      row "Images" do

        ul do

          resource.images.each do |image|

            span(style: 'margin-right: 15px;') do

              image_tag(image, class: "catalogue-image", size: "100x100")

            end

          end

        end

      end

    end

  end

  controller do

    helper_method :subcategories_for_catalogue

    def subcategories_for_catalogue(catalogue)

      if catalogue.category.present?

        BxBlockCategories::Category.find(catalogue.category_id).sub_categories.pluck(:name, :id)

      else

        [] # Return an empty array if no category is selected yet

      end

    end

    def update

      @catalogue = BxBlockCatalogue::Catalogue.find(params[:id])

      if @catalogue.update(permitted_params[:catalogue])

        catalogue_images(@catalogue, params)

      else

        render :edit

      end

    end

    def catalogue_images(catalogue, params)

      @catalogue = catalogue

      if params[:catalogue][:remove_images].present?

        params[:catalogue][:remove_images].reject(&:empty?).each do |image_id|

          @catalogue.images.find(image_id).purge

        end

      end

      @catalogue.images.attach(params[:catalogue][:images]) if params[:catalogue][:images]

      # Remove selected images for catalogue variants

      if params[:catalogue][:catalogue_variants_attributes]

        params[:catalogue][:catalogue_variants_attributes].each do |_, variant_attributes|

          cat_exist_image(@catalogue, variant_attributes)

        end

      end

      # Attach new images for catalogue variants

      if params[:catalogue][:catalogue_variants_attributes]

        params[:catalogue][:catalogue_variants_attributes].each do |_, variant_attributes|

          catalogue_variants_exist_image(@catalogue, variant_attributes)

        end

      end

      redirect_to admin_catalogue_path(@catalogue), notice: "Catalogue updated successfully."

    end

    def cat_exist_image(catalogue, variant_attributes)

      if variant_attributes[:remove_variant_images].present?

        variant_attributes[:remove_variant_images].reject(&:empty?).each do |image_id|

          catalogue.catalogue_variants.find(variant_attributes[:id]).images.find(image_id).purge

        end

      end

    end

    def catalogue_variants_exist_image(catalogue, variant_attributes)

      if variant_attributes[:images].present?

        check_catalogue_variant_new_record(catalogue, variant_attributes)

      end

    end

    def check_catalogue_variant_new_record(catalogue, variant_attributes)

      if variant_attributes[:id].present?

        variant_id = variant_attributes[:id].to_i

        catalogue.catalogue_variants.find(variant_id).images.attach(variant_attributes[:images])

      else

        new_variant = catalogue.catalogue_variants.create("catalogue_variant_color_id"=>variant_attributes[:catalogue_variant_color_id], "catalogue_variant_size_id"=>variant_attributes[:catalogue_variant_size_id], "price"=>variant_attributes[:price], "stock_qty"=>variant_attributes[:price], "length"=>variant_attributes[:length], "breadth"=>variant_attributes[:breadth], "height"=>variant_attributes[:height], "block_qty"=>variant_attributes[:block_qty], "sku"=>variant_attributes[:sku],)

        new_variant.images.attach(variant_attributes[:images])

      end

    end

  end

  form do |f|

    f.inputs "Catalogue Details" do

      f.input :name

      f.input :description

      f.input :category_id, as: :searchable_select, collection: BxBlockCategories::Category.all.collect {|var| [var.name, var.id] }, include_blank: false

      # f.input :sub_category_id, as: :searchable_select, collection: BxBlockCategories::SubCategory.all.collect {|var| [var.name, var.id] }, include_blank: false

      # f.input :sub_category_id, as: :searchable_select, collection: []

      f.input :sub_category_id, as: :searchable_select, collection: subcategories_for_catalogue(f.object), include_blank: false

      f.input :sku

      f.input :manufacture_date, as: :date_picker, input_html: { max: Date.current.strftime("%Y-%m-%d") }

      f.input :availability

      f.input :stock_qty

      f.input :account_id, as: :searchable_select, collection: AccountBlock::Account.all.collect {|var| [var.full_name, var.id] }, include_blank: false

      f.input :product_number

      if f.object.images.present?

        f.input :remove_images, as: :check_boxes, collection: f.object.images.map { |image| [image_tag(image, class: 'checkbox-image', style: 'width:50px;height:50px;'), image.id] }, input_html: { class: "custom-checkbox-label" }

      end  

      f.input :images, as: :file, input_html: { multiple: true }, label: "Add New Images"

    end

    f.has_many :catalogue_variants, heading: 'Catalogue Variants', allow_destroy: true, new_record: 'Add Variant' do |variant_form|

      variant_form.input :catalogue_variant_color_id, as: :searchable_select, collection: BxBlockCatalogue::CatalogueVariantColor.all.collect {|var| [var.name, var.id] }, include_blank: false

      variant_form.input :catalogue_variant_size_id, as: :searchable_select, collection: BxBlockCatalogue::CatalogueVariantSize.all.collect {|var| [var.name, var.id] }, include_blank: false

      variant_form.input :price

      variant_form.input :stock_qty

      variant_form.input :length

      variant_form.input :breadth

      variant_form.input :height

      variant_form.input :block_qty

      variant_form.input :sku

      # hint = variant_form.object.images.map do |image|

      #   image_tag(image, style: 'width: 100px; height: 100px;')

      # end.join('<br>').html_safe

      if variant_form.object.images.present?

        variant_form.input :remove_variant_images, as: :check_boxes, collection: variant_form.object.images.map { |image| [image_tag(image, class: 'checkbox-image', style: 'width:50px;height:50px;'), image.id] }, input_html: { class: 'custom-checkbox-label' }

      end  

      variant_form.input :images, as: :file, input_html: { multiple: true }, label: "Add Variant Images"

      # variant_form.input :images, as: :file, input_html: { multiple: true}, :hint => hint

    end

    f.actions

  end

end

Tuesday, 16 January 2024

How to add jquery and bootstrap in rails 7

 1. Add gem: 

gem 'jquery-rails'

gem 'jquery-ui-rails'

gem "bootstrap"

gem "sassc-rails"

Run: bundle install

-----------------------------------------------------------

2. config/initializers/assets.rb

Rails.application.config.assets.precompile += %w( jquery.min.js jquery_ujs.js bootstrap.min.js )

--------------------------------------------------------------------------------------------------------------

3. config/importmap.rb

pin "jquery", to: "jquery.min.js", preload: true
pin "jquery_ujs", to: "jquery_ujs.js", preload: true
pin "bootstrap", to: "bootstrap.min.js", preload: true

---------------------------------------------------------------------------------

4. app/assets/stylesheets/application.scss

@import "bootstrap";

-------------------------------------------------------------------
5. /app/javascript/application.js

import "jquery"
import "jquery_ujs"
import "bootstrap"

Then restart server: rails server


Form tag and auto submit form after 1 sec.

<div class="container-fluid">
  <div class="row mt-4">
    <div class="col-md-6">
    <%= form_tag "/fetch_breed", class: "inline-form", id: "breed_form", remote: true do %>
        <label for="breed">Breed:</label>
        <input type="text" id="bname" name="breed" class="form-control" value="affenpinscher">
        <button type="submit" class="btn btn-success">Submit</button>
      <% end %>
    </div>
    <div class="col-md-6">
      <div class="show_breed"></div>
    </div>
  </div>
</div>

<script type="text/javascript">
setTimeout(() => {
  $("#breed_form").submit();
}, "1000");
</script>


Wednesday, 10 January 2024

How to run react native application step by step without emulator

Note: Your mobile must have developer options is ON

Please visit one https://www.youtube.com/watch?v=r33OwlTnTE4

 Step 1. Make sure your system install or not android studio

Install Android studio: https://www.geeksforgeeks.org/how-to-install-android-studio-on-ubuntu/


Run this $ echo $ANDROID_HOME

getting this results: /home/zzzz/Android/Sdk

----------------------------------------------------------------

Step 2. Create new application

     npx react-native@latest init ProjectName

-----------------------------------------------------------------

Step 3. Please connect your mobile with USB cable

Choose  this line : File tranfer/Android Auto

-------------------------------------------------------------

Run on Phisical device

Visite this site: https://github.com/arvindkushwah9/React-Native-Example

Step 4. projects$   lsusb

        Make sure your device is connected or not

Getting lists of all devices result:

Bus 002 Device 001: ID aaaaaa:aaaaaa Linux Foundation 3.0 root hub

Bus 001 Device 005: ID bbbbb:bbbbbb Chicony Electronics Co., Ltd Integrated Camera

Bus 001 Device 004: ID ccccc:eeeee Intel Corp. 

Bus 001 Device 003: ID vvvvv:ddddd Dell Computer Corp. Dell MS116 USB Optical Mouse

Bus 001 Device 006: ID XXXX:ffff Xiaomi Inc. Mi/Redmi series (MTP + ADB)

Bus 001 Device 001: ID bbbb:bbbbb Linux Foundation 2.0 root hub

My device ID is Xiaomi and device id XXXX 

--------------------------------------------------------------

Step 5. run this line in the project directry

echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-android-usb.rules

-----------------------------------------------------------------------

Step 6. Run: npx react-native run-android

Install via USB is ON << under the Developer options

---------------------------------------------------------------------

Step 7. Run: npx react-native start







Wednesday, 20 December 2023

Set time zone with timezone

 1. active admin side:

ActiveAdmin.register BxBlockEvents::Event, as: 'Event' do

  Formtastic::FormBuilder.perform_browser_validations = true


  permit_params :title, :is_active, :time, :date, :latitude, :longitude, :assign_to, :email_account_id, :notify, :repeat, :notes, :visibility, :event_type, :address, :custom_repeat_in_number, :custom_repeat_every, :assignee_email, :visible_email, :format, :description, :start_date, :end_date, :timezone, :cvent_id, :status, :cvent_response_code, :event_creation_id, :is_feature_event, :venue_id, :is_booking_start, planner_attributes: [:id, :prefix, :first_name, :last_name, :company, :title, :email, :_destroy, addresses_attributes: [:id, :region_code, :address1, :address2, :address3, :city, :country_code, :postal_code, :latitude, :longitude, :address_type, :_destroy]]



  index do

    selectable_column

    id_column

    column :title

    toggle_bool_column :is_active

    column :cvent_id

    column :status

    column :event_creation_id

    toggle_bool_column :is_booking_start

    column "" do |resource|

      links = ''.html_safe

      links += link_to I18n.t('active_admin.view'), resource_path(resource), class: "member_link_event show_link"

      if resource.status == "Created"

        links += link_to I18n.t('active_admin.edit'), edit_resource_path(resource), class: "member_link_event edit_link"

      end

      links += link_to I18n.t('active_admin.delete'), resource_path(resource), method: :delete, 'data-confirm' => I18n.t('active_admin.delete_confirmation'), class: "member_link_event delete_link"

      links

    end

  end


  show do

    attributes_table do

      row:title

      row:time

      row:date

      row:latitude

      row:longitude

      row:assign_to

      row:email_account_id

      row:notify

      row:repeat

      row:notes

      row:visibility

      row:created_at

      row:updated_at

      row:event_type

      row:address

      row:custom_repeat_in_number

      row:custom_repeat_every

      row:assignee_email

      row:visible_email

      row:format

      row:description

      row:start_date

      row:end_date

      row:timezone

      row:cvent_id

      row:status

      row:cvent_response_code

      row:event_creation_id

      row:is_active

      row:is_feature_event

      row:is_booking_start

    end

    panel 'Sessions' do

      table_for event.event_sessions do

        column :id do |object|

            link_to object&.id, "/admin/event_sessions/#{object&.id}"

          end

        column :title

        column :status

      end

    end

  end

  controller do

    helper_method :fetch_speakers_for_select

    around_action :set_time_zone

    def set_time_zone

      if (params[:action] == "create") || (params[:action] == "update")

        Time.use_zone(params[:event][:timezone]) { yield }

      elsif params[:action] == "edit" || params[:action] == "show"

        Time.use_zone(resource.timezone) { yield }

      else

        yield

      end

    end

    def fetch_speakers_for_select(event)

      accepted_speaker_ids = event.user_events.where(status: 'accept').pluck(:account_id)

      AccountBlock::Account.speakers.map do |speaker|

        speaker_name = "#{speaker.first_name} #{speaker.last_name}"

        disabled = accepted_speaker_ids.include?(speaker.id)

        [speaker_name, speaker.id, { disabled: disabled }]

      end

    end

    def create

      super

      user_event = params[:event][:speaker_account_ids].reject { |e| e.nil? || e&.empty? }

      if user_event.present?

        user_event.each do |user|

          invitation = BxBlockEvents::UserEvent.create(account_id: user.to_i, event_id: resource.id)

          headings = resource&.title.to_s

          content = resource&.title.to_s

          message = "<p>We inform you that you have been invited to the event " + "<b>#{resource&.title.to_s}</b>" + " which we hope will be of interest to you.</p>"

          app_url = "event_invite"

          module_type = "Event"

          BxBlockNotifications::NotificationCreator.new(user.to_i, headings, content, app_url, resource.id, module_type, message, invitation.id).call if invitation&.id.present?

        end

      end

      if params[:event][:images].present?

        resource.event_images.attach(params[:event][:images])

      end

    end


    def update

      super do |success, failure|

        if success.present? && (!params[:event][:is_active].to_s.present? && !params[:event][:is_booking_start].to_s.present? )

          new_or_exit_ids = params[:event][:speaker_account_ids].reject { |e| e.nil? || e&.empty? } rescue []

          already_speaker_ids = resource.user_events.where.not(status: "accept").map(&:account_id).map{|sp| sp.to_s}

          remove_speaker_ids = already_speaker_ids - new_or_exit_ids

          new_speaker_ids = new_or_exit_ids - already_speaker_ids

          delete_invitation(resource, remove_speaker_ids)

          new_speaker_ids.each do |user|

            invitation = BxBlockEvents::UserEvent.create(account_id: user.to_i, event_id: resource.id)

            headings = resource&.title.to_s

            content = resource&.title.to_s

            app_url = "event_invite"

            message = "<p>We inform you that you have been invited to the event " + "<b>#{resource&.title.to_s}</b>" + " which we hope will be of interest to you.</p>"

            module_type = "Event"

            BxBlockNotifications::NotificationCreator.new(user.to_i, headings, content, app_url, resource.id, module_type, message, invitation.id).call if invitation&.id.present?

          end

          if params[:event][:images].present?

            resource.event_images.destroy_all

            resource.event_images.attach(params[:event][:images])

          end

        end

      end

    end

    private

    def delete_invitation(resource, remove_speaker_ids)

      resource.user_events.where(account_id: remove_speaker_ids).destroy_all

    end

  end


  form do |f|

    f.inputs do

      # f.semantic_errors *f.object.errors.keys

      f.semantic_errors :cvent_id

      f.input :title

      # f.input :email_account_id, label: 'Account', as: :select, collection: AccountBlock::Account.all.map{|e| ["#{e.first_name} #{e.last_name}",e.id]}, include_blank: false, :input_html => {:width => 'auto'}


      f.input :speaker_account_ids, label: 'Add speakers', as: :select, collection: fetch_speakers_for_select(f.object), selected: f.object.user_events.map(&:account_id), include_blank: false, :input_html => {:width => 'auto', multiple: true}


      f.input :format, include_blank: false

      if f.object.new_record?

        f.input :start_date, as: :date_time_picker, :input_html => {:width => 'auto'}

        f.input :end_date, as: :date_time_picker, :input_html => {:width => 'auto'}

      else

        f.input :start_date, as: :date_time_picker, :input_html => {:width => 'auto', :value => f.object.start_date.in_time_zone(f.object.timezone)}

        f.input :end_date, as: :date_time_picker, :input_html => {:width => 'auto', :value => f.object.end_date.in_time_zone(f.object.timezone)}

      end

      f.input :timezone, :as => :select, :collection => ([["Asia/Calcutta", "Asia/Calcutta"], ["Asia/Dubai", "Asia/Dubai"], ["Europe/London", "Europe/London"], ["Europe/Paris", "Europe/Paris"], ["Australia/Darwin", "Australia/Darwin"], ["Australia/Adelaide", "Australia/Adelaide"], ["America/Mexico_City", "America/Mexico_City"], ["America/New_York", "America/New_York"]]), include_blank: false

      f.input :images, label: 'Add image', as: :file

      f.object.event_images.each do |img|

        span do

          image_tag(img,height: '80', width: '100') rescue nil

        end

      end

      # f.input :time, :as => :time_picker

      # f.input :date

      # f.input :latitude

      # f.input :longitude

      # f.input :assign_to

      # f.input :notify

      # f.input :repeat

      # f.input :notes

      f.input :visibility

      f.input :event_type, :as => :select, :collection => ([["Celebration", "Celebration"], ["Conference", "Conference"], ["Dinner", "Dinner"], ["Forum", "Forum"], ["FundraiserBenefit", "FundraiserBenefit"], ["Holiday", "Holiday"], ["IncentiveTrip", "IncentiveTrip"], ["Meeting", "Meeting"], ["OtherGeneral", "OtherGeneral"], ["PoliticalEvent", "PoliticalEvent"], ["Reunion", "Reunion"], ["SaveTheDate", "SaveTheDate"], ["Seminar", "Seminar"], ["SportsEvent", "SportsEvent"], ["TradeShow", "TradeShow"], ["TrainingSession", "TrainingSession"], ["Webinar", "Webinar"]]), include_blank: false

      f.input :address

      f.input :custom_repeat_in_number

      f.input :custom_repeat_every

      f.input :assignee_email

      f.input :visible_email

      f.input :description, input_html: {required: true}

      f.input :is_feature_event

    end

    f.inputs 'Venues' do

      f.input :venue_id, as: :select, collection: BxBlockEvents::Venue.all.map{|v| ["#{v.name}", v.id]}, :input_html => {}, include_blank: false

    end


    f.inputs 'Planners' do

      f.inputs :for => [:planner, f.object.planner || BxBlockEvents::Planner.new] do |planner|

        planner.input :prefix

        planner.input :first_name

        planner.input :last_name

        planner.input :company

        planner.input :title

        planner.input :email

      end

    end


    f.inputs 'Planner addresses' do

      f.inputs :for => ['home_address', (resource&.planner&.addresses.where(address_type: "home_address").last rescue nil || BxBlockEvents::Address.new)] do |pha|

        f.inputs 'Home address' do

          pha_id = resource&.planner&.addresses.where(address_type: "home_address").last.present? ? resource&.planner&.addresses.where(address_type: "home_address").last&.id : nil rescue nil

          pha.input :id, input_html: {:value => pha_id, name: "event[planner_attributes][addresses_attributes][0][id]"}, as: :hidden

          pha.input :region_code, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][region_code]", maxlength: 9}

          pha.input :address1, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][address1]", maxlength: 35}

          pha.input :address2, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][address2]", maxlength: 35}

          pha.input :address3, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][address3]", maxlength: 35}

          pha.input :city, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][city]", maxlength: 30}

          pha.input :country_code, :as => :select, :collection => (ISO3166::Country.codes.map{|code| code}), include_blank: false, input_html: {name: "event[planner_attributes][addresses_attributes][0][country_code]", maxlength: 3}

          pha.input :postal_code, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][0][postal_code]", maxlength: 24}

          pha.input :address_type, :input_html => { :value => "home_address", name: "event[planner_attributes][addresses_attributes][0][address_type]" }, as: :hidden

        end

      end

      f.inputs :for => ['work_address', (resource&.planner&.addresses.where(address_type: "work_address").last rescue nil || BxBlockEvents::Address.new)] do |pwa|

        f.inputs 'Work address' do

          pwa_id = resource&.planner&.addresses.where(address_type: "work_address").last.present? ? resource&.planner&.addresses.where(address_type: "work_address").last&.id : nil rescue nil

          pwa.input :id, input_html: {:value => pwa_id, name: "event[planner_attributes][addresses_attributes][1][id]"}, as: :hidden

          pwa.input :region_code, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][region_code]", maxlength: 9}

          pwa.input :address1, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][address1]", maxlength: 35}

          pwa.input :address2, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][address2]", maxlength: 35}

          pwa.input :address3, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][address3]", maxlength: 35}

          pwa.input :city, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][city]", maxlength: 30}

          pwa.input :country_code, :as => :select, :collection => (ISO3166::Country.codes.map{|code| code}), include_blank: false, input_html: {name: "event[planner_attributes][addresses_attributes][1][country_code]", maxlength: 3}

          pwa.input :postal_code, input_html: {required: true, name: "event[planner_attributes][addresses_attributes][1][postal_code]", maxlength: 24}

          pwa.input :address_type, :input_html => { :value => "work_address", name: "event[planner_attributes][addresses_attributes][1][address_type]" }, as: :hidden

        end

      end

    end

    

    f.actions

  end  

end

----------------------------------------------------------------------------

2. Normal controller OR view

Add this line application controller OR and where necessary :
around_action :set_time_zone
def set_time_zone
    if session[:timezone].present?
      Time.use_zone('New Delhi') { yield }
    else
      yield
    end    
  end

Thursday, 26 October 2023

How to fixed left menu dropdown in active admin

 JS: app/assets/javascripts/active_admin.js

$(document).ready(function() {

  $(".menu_item.current").addClass("open");

});

----------------------------------------------------

CSS: app/assets/stylesheets/active_admin.scss

.header #tabs li.has_nested.open > a:nth-child(1)::after{

  content: "\f0de" !important; #this is open

}

.header #tabs li.has_nested > a:nth-child(1)::after{

  content: "\f0dd" !important; #this is close

}

.header #tabs li.has_nested.open > ul{

  display: block !important;

}

.header #tabs li.has_nested > ul{

  display: none !important;

}








Monday, 16 October 2023

How to add address picker in active admin step by step

1. app/admin/venues.rb 

ActiveAdmin.register BxBlockEvents::Venue, as: "Venue" do

  Formtastic::FormBuilder.perform_browser_validations = true

  actions :all, except: [:destroy]

  permit_params :name, address_attributes: [:id, :region_code, :address_criteria, :address1, :address2, :address3, :city, :country_code, :postal_code, :latitude, :longitude, :address_type, :_destroy]


  show :title => proc {|venue| venue.name.to_s } do

    attributes_table do

      row "Venue name" do |object|

        object&.name

      end

    end

    panel 'Venue address' do

      attributes_table_for venue.address do

        row :id

        row "State Code" do |object|

          object&.region_code

        end

        row :address_criteria

        row :address1

        row :address2

        row :address3

        row :city

        row :country_code

        row :postal_code

        row :latitude

        row :longitude

      end

    end

  end

  form do |f|

    f.inputs do

      f.input :name, label: 'Venue name'

    end

    f.inputs 'Venue address' do

      f.inputs :for => [:address, f.object.address || BxBlockEvents::Address.new] do |a|

        a.input :address_criteria, input_html: {required: true}

        a.input :address1, input_html: {required: true, maxlength: 35}

        a.input :address2, input_html: {maxlength: 35} 

        a.input :address3, input_html: {maxlength: 35}

        a.input :city, input_html: {id: 'city', required: true, maxlength: 30}

        a.input :region_code, label: 'State Code', input_html: {id: 'state', required: true, maxlength: 9}

        a.input :country_code, input_html: { id: 'country', maxlength: 3, readonly: true}

        a.input :postal_code, input_html: { id: 'postcode', maxlength: 24, readonly: true}

        a.input :latitude, as: :hidden, input_html: { id: 'latitude' }

        a.input :longitude, as: :hidden, input_html: { id: 'longitude' }

      end

    end

    f.actions

  end

end




================================================================

2. app/assets/javascripts/venue_address.js.erb

    2.1 isme state and country name short use kiye hai

        $(document).ready(function() {

  let input = document.getElementById('venue_address_attributes_address_criteria');

  let autocomplete = new google.maps.places.Autocomplete(input);


  autocomplete.addListener('place_changed', function() {

    let place = autocomplete.getPlace();

    if (place.geometry && place.geometry.location) {

      let addressComponents = place.address_components.map(function(component) {

        return {

          type: component.types[0],

          name: component.short_name

        };

      });


      addressComponents.sort(function(a, b) {

        return a.name.localeCompare(b.name);

      });


      let state = '';

      let country = '';


      for (let component of addressComponents) {

        if (component.type === 'administrative_area_level_1') {

          state = component.name;

        } else if (component.type === 'country') {

          country = component.name;

        }

      }


      document.getElementById('country').value = country;

      document.getElementById('state').value = state;

      document.getElementById('city').value = extractAddressComponent(place, 'locality');

      document.getElementById('postcode').value = extractAddressComponent(place, 'postal_code');

      document.getElementById('latitude').value = place.geometry.location.lat();

      document.getElementById('longitude').value = place.geometry.location.lng();

    }

  });

});


function extractAddressComponent(place, componentType) {

  for (let component of place.address_components) {

    for (let type of component.types) {

      if (type === componentType) {

        return component.long_name;

      }

    }

  }

  return '';

}

-------------------------------------------------------------------------------------------

2.2 Get full state name and country name of this code


    $(document).ready(function() {

      var input = document.getElementById('venue_address_attributes_address_criteria');

      var autocomplete = new google.maps.places.Autocomplete(input);


      // Listener for the 'place_changed' event on the current location autocomplete

      autocomplete.addListener('place_changed', function() {

        var place = autocomplete.getPlace();

        if (place.geometry && place.geometry.location) {

          document.getElementById('country').value = extractAddressComponent(place, 'country');

          document.getElementById('state').value = extractAddressComponent(place, 'administrative_area_level_1');

          document.getElementById('city').value = extractAddressComponent(place, 'locality');

          document.getElementById('postcode').value = extractAddressComponent(place, 'postal_code');

          document.getElementById('latitude').value = place.geometry.location.lat();

          document.getElementById('longitude').value = place.geometry.location.lng();

        }

      });

    });


    function extractAddressComponent(place, componentType) {

      for (var i = 0; i < place.address_components.length; i++) {

        for (var j = 0; j < place.address_components[i].types.length; j++) {

          if (place.address_components[i].types[j] === componentType) {

            return place.address_components[i].long_name;

          }

        }

      }

      return '';

    }


    google.maps.event.addDomListener(window, 'load', initialize);


=======================================================

3. app/assets/javascripts/active_admin.js

# require venue_address.js file

//= require venue_address

===========================================================

4. app/config/initializers/active_admin.rb

    config.register_javascript "https://maps.googleapis.com/maps/api/js?key=#{ENV['GOOGLE_API_KEY']}&callback=initAutocomplete&libraries=places&v=weekly"


=============================================================

5. rails server restart: rails s



========================================


partial form: 

1. app/admin/users.rb

controller do

    def build_new_resource

      super.tap { |resource| resource.build_address }

    end


    def find_resource

      super.tap do |resource|

        resource.build_address unless resource.address.present?

      end

    end

end

form do |f|

    render 'form', context: self, f: f

  end

=====================================================

1. app/views/admin/venues/_form.html.erb

<% context.instance_eval do

    semantic_form_for resource, url: admin_venues_path do

  # f.semantic_errors *f.object.errors.keys

      f.inputs 'Vanue name' do

f.input :name, required: true, :as => :string, label: "Name"

  end

f.inputs 'Vanue address' do

    f.semantic_fields_for :address do |s|

          s.input :address_criteria

      s.input :address1

      s.input :address2

      s.input :address3

      s.input :city, input_html: { id: 'city', readonly: true }

      s.input :region_code, input_html: { id: 'state', readonly: true }

      s.input :postal_code, input_html: { id: 'postcode', readonly: true }

      s.input :country_code, input_html: { id: 'country', readonly: true }

      s.input :latitude, input_html: { id: 'latitude', readonly: true }

      s.input :longitude, input_html: { id: 'longitude', readonly: true }

    end

  end


  f.actions

  end

  end

%>

------------------------------------------------------------------
























Thursday, 5 October 2023

On Change get sub category, based on category in admin side

 1. app/assets/javascripts/active_admin.js

$(document).on('change', '#bx_block_latest_news_latest_new_category_id', function () {

  var categoryId = $(this).val();

  $.ajax({

    url: '/accounts/sub_categories.json',

    method: 'GET',

    data: { category_id: categoryId },

    dataType: 'json',

    success: function (data) {

      var subcategorySelect = $('#product_subcategory_id');

      subcategorySelect.empty();

      $.each(data, function (key, value) {

        subcategorySelect.append($('<option>').text(value.name).attr('value', value.id));

      });

    }

  });

});


-------------------------------------------------------------


2. Routes.rb

resources :accounts, :only => [:create, :destroy] do

      get 'sub_categories', on: :collection

    end

---------------------------------------------------------------

3. admin/users.rb


form do |f|

    f.inputs do

    f.input :category_id, as: :select, collection: BxBlockCategories::Category.all.map{|e| ["#{e.name}", e.id]}, :input_html => {}, include_blank: false

      f.input :title, as: :select, collection: [], input_html: { id: 'product_subcategory_id' }

      # f.input :title

      f.input :description, :as => :ckeditor

      f.input :image, label: 'Add image', as: :file, :input_html => {}

      span do

        image_tag(object.image, height: '80', width: '100') rescue nil

      end

    end

    f.actions do

      if resource.persisted?

        f.action :submit, as: :button, label: 'Update Latest news'

      else

        f.action :submit, as: :button, label: 'Create Latest News'

      end

      f.action :cancel, as: :link, label: 'Cancel'

    end

  end


------------------------------------------------------------------------------

4. accounts_controller.rb


def sub_categories

      all_df = BxBlockCategories::SubCategory.all

      render json: all_df

    end


--------------------------------------------------------


yadi update karte hai to, selected data ana chahiye

admin/users.rb

controller do

    helper_method :options_for_sub_categories

    def options_for_sub_categories

      categories_and_subcategories = []

      BxBlockCategories::Category.all.each do |category|

        categories_and_subcategories << ["Category: #{category.name}", category.id, { disabled: true }]

        category.sub_categories.each do |sub_category|

          categories_and_subcategories << ["#{sub_category.name}", sub_category.id]

        end

      end

      return categories_and_subcategories

    end

  end


---------------------------------------------------------------------

admin/users.rb

form do |f|

    f.inputs "Catalogue Details" do

      # f.input :category_id, as: :searchable_select, collection: BxBlockCategories::Category.all.collect {|var| [var.name, var.id] }, include_blank: false

      # f.input :sub_category_id, as: :searchable_select, collection: BxBlockCategories::SubCategory.all.collect {|var| [var.name, var.id] }, include_blank: false

      # f.input :sub_category, as: :select, collection: options_for_sub_categories(f.object.category_id), include_blank: 'Select a Sub-Category'