Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: [FEAT] Custom Links in Dropdown Menu #5718

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5c15b07
feat: add migration and model for custom links
nepaakash May 13, 2024
10e78b9
feat: update the schema information
nepaakash May 13, 2024
5910151
feat: add factory and spec file
nepaakash May 13, 2024
88e5893
Merge remote-tracking branch 'origin/main' into feat/custom-links-in-…
nepaakash Jun 23, 2024
22fbe5b
feat: add setter for custom url
nepaakash Jun 23, 2024
e046020
feat: add custom link section in edit organization page
nepaakash Jun 23, 2024
a697e10
fet: add before action and update setter name
nepaakash Jun 23, 2024
c25ba65
feat: add soft delete column to custom links table
nepaakash Jun 23, 2024
53b95c2
feat: add active scope to custom link class
nepaakash Jun 23, 2024
33a0d41
feat: add active column to custom links table
nepaakash Jun 23, 2024
ebbb863
feat: update destroy popup text
nepaakash Jun 23, 2024
ab5454a
feat: add custom link policy
nepaakash Jun 23, 2024
a7b39b3
feat: add route and controller for custom link policy
nepaakash Jun 23, 2024
be36735
feat: add views for crud
nepaakash Jun 23, 2024
9a5df29
feat: add association with custom links
nepaakash Jun 23, 2024
e801d16
feat: add active column and soft delete validations
nepaakash Jun 23, 2024
3fd889b
feat: remove unused methods
nepaakash Jun 23, 2024
c3dcacb
feat: add validation for text and url
nepaakash Jun 23, 2024
136111b
feat: add custom link to the profile dropdown
nepaakash Jun 23, 2024
8fb37fa
fix: linter issue fix
nepaakash Jun 23, 2024
cce5956
feat: update factory for custom link
nepaakash Jun 23, 2024
1d0d5d7
fix: linters issue fixed
nepaakash Jun 23, 2024
4942caf
fix: fix model spec linter
nepaakash Jun 23, 2024
f020367
feat: add casa org association in custom link factory
nepaakash Jun 23, 2024
4d2d99b
fix: linter issue fix
nepaakash Jun 23, 2024
e905bb1
fix: return if current organization is not present
nepaakash Jun 29, 2024
dded9f9
feat: remove soft delete feature from custom link
nepaakash Jun 29, 2024
990f96b
feat: add icon for the custom link
nepaakash Jun 29, 2024
3f6847f
feat: include destroy method in custom link policy
nepaakash Jun 29, 2024
b8f25bf
feat: remove sof delete validation and condition
nepaakash Jun 29, 2024
a514b3f
fix: linter issue fix
nepaakash Jun 29, 2024
6d8a7aa
feat: add test case fir custom link
nepaakash Aug 26, 2024
8b923fd
Merge remote-tracking branch 'origin/main' into feat/custom-links-in-…
nepaakash Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 27 additions & 26 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
before_action :set_timeout_duration
before_action :set_current_organization
before_action :set_active_banner
before_action :set_custom_links
after_action :verify_authorized, except: :index, unless: :devise_controller?
# after_action :verify_policy_scoped, only: :index

Expand Down Expand Up @@ -42,27 +43,31 @@ def set_active_banner
@active_banner = nil if @active_banner&.expired?
end

def set_custom_links
return unless current_organization

@custom_links = current_organization.custom_links.active
end

protected

def handle_short_url(url_list)
hash_of_short_urls = {}
url_list.each_with_index { |val, index|
url_list.each_with_index do |val, index|
# call short io service to shorten url
# create an entry in hash if api is success
short_io_service = ShortUrlService.new
response = short_io_service.create_short_url(val)
short_url = short_io_service.short_url
hash_of_short_urls[index] = (response.code == 201 || response.code == 200) ? short_url : nil
}
hash_of_short_urls[index] = response.code == 201 || response.code == 200 ? short_url : nil
end
hash_of_short_urls
end

# volunteer/supervisor/casa_admin controller uses to send SMS
# returns appropriate flash notice for SMS
def deliver_sms_to(resource, body_msg)
if resource.phone_number.blank? || !resource.casa_org.twilio_enabled?
return "blank"
end
return 'blank' if resource.phone_number.blank? || !resource.casa_org.twilio_enabled?

body = body_msg
to = resource.phone_number
Expand All @@ -77,32 +82,32 @@ def deliver_sms_to(resource, body_msg)

begin
twilio_res = @twilio.send_sms(req_params)
twilio_res.error_code.nil? ? "sent" : "error"
rescue Twilio::REST::RestError => error
@error = error
"error"
rescue # unverfied error isnt picked up by Twilio::Rest::RestError
twilio_res.error_code.nil? ? 'sent' : 'error'
rescue Twilio::REST::RestError => e
@error = e
'error'
rescue StandardError # unverfied error isnt picked up by Twilio::Rest::RestError
# https://www.twilio.com/docs/errors/21608
@error = "Phone number is unverifiied"
"error"
@error = 'Phone number is unverifiied'
'error'
end
end

def sms_acct_creation_notice(resource_name, sms_status)
case sms_status
when "blank"
when 'blank'
"New #{resource_name} created successfully."
when "error"
when 'error'
"New #{resource_name} created successfully. SMS not sent. Error: #{@error}."
when "sent"
when 'sent'
"New #{resource_name} created successfully. SMS has been sent!"
end
end

def store_referring_location
if request.referer && !request.referer.end_with?("users/sign_in") && params[:ignore_referer].blank?
session[:return_to] = request.referer
end
return unless request.referer && !request.referer.end_with?('users/sign_in') && params[:ignore_referer].blank?

session[:return_to] = request.referer
end

def redirect_back_to_referer(fallback_location:)
Expand Down Expand Up @@ -136,22 +141,18 @@ def set_current_organization

def not_authorized
session[:user_return_to] = nil
flash[:notice] = "Sorry, you are not authorized to perform this action."
flash[:notice] = 'Sorry, you are not authorized to perform this action.'
redirect_to(root_url)
end

def log_and_reraise(error)
unless KNOWN_ERRORS.include?(error.class)
Bugsnag.notify(error)
end
Bugsnag.notify(error) unless KNOWN_ERRORS.include?(error.class)
raise
end

def check_unconfirmed_email_notice(user)
notice = "#{user.role} was successfully updated."
if user.saved_changes.include?("unconfirmed_email")
notice += " Confirmation Email Sent."
end
notice += ' Confirmation Email Sent.' if user.saved_changes.include?('unconfirmed_email')
notice
end
end
5 changes: 5 additions & 0 deletions app/controllers/casa_org_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class CasaOrgController < ApplicationController
before_action :set_learning_hour_topics, only: %i[edit update]
before_action :set_sent_emails, only: %i[edit update]
before_action :set_contact_topics, only: %i[edit update]
before_action :set_custom_links, only: %i[edit update]
before_action :require_organization!
after_action :verify_authorized
before_action :set_active_storage_url_options, only: %i[edit update]
Expand Down Expand Up @@ -90,6 +91,10 @@ def set_contact_topics
@contact_topics = @casa_org.contact_topics.where(soft_delete: false)
end

def set_custom_links
@custom_links = @casa_org.custom_links.where(soft_delete: false)
end

def set_active_storage_url_options
ActiveStorage::Current.url_options = {host: request.base_url}
end
Expand Down
61 changes: 61 additions & 0 deletions app/controllers/custom_links_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
class CustomLinksController < ApplicationController
before_action :set_custom_link, only: %i[edit update destroy]

# GET /custom_links/new
def new
authorize CustomLink
custom_link = CustomLink.new(casa_org_id: current_user.casa_org_id)
@custom_link = custom_link
end

# GET /custom_links/1/edit
def edit
authorize @custom_link
end

# POST /custom_links
def create
authorize CustomLink

@custom_link = CustomLink.new(custom_link_params)

if @custom_link.save
redirect_to edit_casa_org_path(current_organization), notice: "Custom link was successfully created."
else
render :new
end
end

# PATCH/PUT /custom_links/1
def update
authorize @custom_link
if @custom_link.update(custom_link_params)
redirect_to edit_casa_org_path(current_organization), notice: "Custom link was successfully updated."
else
render :edit
end
end

# DELETE /custom_links/1/delete
def destroy
authorize @custom_link

if @custom_link.destroy
redirect_to edit_casa_org_path(current_organization), notice: "Custom link was successfully removed."
else
render :show, status: :unprocessable_entity
end
end

private

# Use callbacks to share common setup or constraints between actions.
def set_custom_link
@custom_link = CustomLink.find(params[:id])
end

# Only allow a list of trusted parameters through.
def custom_link_params
params.require(:custom_link).permit(:text, :url, :active, :casa_org_id)
end
end
1 change: 1 addition & 0 deletions app/models/casa_org.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CasaOrg < ApplicationRecord
has_many :learning_hour_topics, dependent: :destroy
has_many :case_groups, dependent: :destroy
has_many :contact_topics
has_many :custom_links
has_one_attached :logo
has_one_attached :court_report_template

Expand Down
31 changes: 31 additions & 0 deletions app/models/custom_link.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class CustomLink < ApplicationRecord
belongs_to :casa_org
# Validate that the URL is present, has a valid format, and is unique
validates :url, presence: true,
format: {with: /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/, message: "must be a valid URL"}
# Validate that the title is present and has a maximum length of 255 characters
validates :text, presence: true, length: {maximum: 255}

scope :active, -> { where(active: true) }
end

# == Schema Information
#
# Table name: custom_links
#
# id :bigint not null, primary key
# active :boolean default(TRUE), not null
# text :string
# url :text
# created_at :datetime not null
# updated_at :datetime not null
# casa_org_id :bigint not null
#
# Indexes
#
# index_custom_links_on_casa_org_id (casa_org_id)
#
# Foreign Keys
#
# fk_rails_... (casa_org_id => casa_orgs.id)
#
8 changes: 8 additions & 0 deletions app/policies/custom_link_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CustomLinkPolicy < ApplicationPolicy
alias_method :create?, :is_admin_same_org?
alias_method :edit?, :is_admin_same_org?
alias_method :new?, :is_admin_same_org?
alias_method :show?, :is_admin_same_org?
alias_method :update?, :is_admin_same_org?
alias_method :destroy?, :is_admin_same_org?
end
64 changes: 64 additions & 0 deletions app/views/casa_org/_custom_links.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<div class="row">
<div class="col-lg-12">
<div class="card-style mb-30">
<div class="row align-items-center">
<div class="col-md-6">
<h3>Custom Link</h3>
</div>
<div class="col-md-6">
<div class="breadcrumb-wrapper">
<span class="ml-5">
<%= link_to new_custom_link_path, class: "btn-sm main-btn primary-btn btn-hover" do %>
<i class="lni lni-plus mr-10"></i>
New Custom Link
<% end %>
</span>
</div>
</div>
</div>
<div class="table-wrapper table-responsive">
<table class="table striped-table" id="contact-topics">
<thead>
<tr>
<th>Display Text</th>
<th>URL</th>
<th>Active?</th>
</tr>
</thead>
<tbody>
<% @custom_links.each do |custom_link| %>
<% id = "custom_link-#{custom_link.id}" %>
<tr>
<td scope="row" class="min-width">
<%= custom_link.text %>
</td>
<td scope="row" class="min-width pre-line"><%= custom_link.url %></td>
<td scope="row" class="min-width">
<%= custom_link.active ? "Yes" : "No" %>
</td>
<td>
<%= render(DropdownMenuComponent.new(menu_title: "Actions Menu", hide_label: true)) do %>
<li><%= link_to "Edit", edit_custom_link_path(custom_link), class: "dropdown-item" %></li>
<li><%= render(Modal::OpenLinkComponent.new(text: "Delete", target: id, klass: "dropdown-item")) %></li>
<% end %>
</td>
</tr>
<%= render(Modal::GroupComponent.new(id: id)) do |component| %>
<% component.with_header(text: "Delete Custom Link?", id: id) %>
<% component.with_body(text: [
"This custom link will be deleted and will no longer be visible in profile dropdown."]) %>
<% component.with_footer do %>
<%= link_to custom_link_path(custom_link), method: :delete,
class: "btn-sm main-btn danger-btn btn-hover ms-auto" do %>
<i class="lni lni-trash-can mr-10"></i>
Delete Custom Link
<% end %>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
14 changes: 14 additions & 0 deletions app/views/casa_org/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,17 @@
<div class="tables-wrapper">
<%= render "contact_topics" %>
</div>
<div class="title-wrapper pt-30">
<div class="row align-items-center">
<div class="col-md-6">
<div class="title mb-30">
<h2>
Manage Custom Links
</h2>
</div>
</div>
</div>
</div>
<div class="tables-wrapper">
<%= render "custom_links" %>
</div>
39 changes: 39 additions & 0 deletions app/views/custom_links/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<div class="title-wrapper pt-30">
<div class="row align-items-center">
<div class="col-md-6">
<div class="title mb-30">
<h1>
<%= title %>
</h1>
</div>
</div>
</div>
</div><!-- ==== end title ==== -->

<!-- ========== card start ========== -->
<div class="card-style mb-30">
<%= form_with(model: custom_link, local: true) do |form| %>
<%= form.hidden_field :casa_org_id %>
<div class="alert-box danger-alert">
<%= render "/shared/error_messages", resource: custom_link %>
</div>
<div class="input-style-1">
<%= form.label :text, "Display Text" %>
<%= form.text_field :text, class: "form-control", required: true %>
</div>
<div class="input-style-1">
<%= form.label :url, "URL" %>
<%= form.text_field :url, rows: 5, class: "form-control", required: true %>
</div>
<div class="form-check checkbox-style mb-20">
<%= form.check_box :active, class: 'form-check-input' %>
<%= form.label :active, "Active?", class: 'form-check-label' %>
</div>
<div class="actions mb-10">
<%= button_tag(type: "submit", class: "btn-sm main-btn primary-btn btn-hover") do %>
<i class="lni lni-checkmark-circle mr-5"></i> Submit
<% end %>
</div>
<% end %>
</div>
<!-- card end -->
1 change: 1 addition & 0 deletions app/views/custom_links/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= render partial: "form", locals: {title: "Custom Link", custom_link: @custom_link} %>
1 change: 1 addition & 0 deletions app/views/custom_links/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= render partial: "form", locals: {title: "New Custom Link", custom_link: @custom_link} %>
7 changes: 7 additions & 0 deletions app/views/layouts/_header.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@
<strong> <%= current_user.email %></strong>
</span>
</li>
<% @custom_links.each do |custom_link| %>
<li>
<%= link_to custom_link.url, target: "_blank" do %>
<i class="lni lni-link"></i> <%= custom_link.text %>
<% end %>
</li>
<% end %>
<li>
<%= link_to edit_users_path do %>
<i class="lni lni-pencil"></i>
Expand Down
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@
delete "soft_delete", on: :member
end

resources :custom_links, except: %i[index show] do
end

resources :followup_reports, only: :index
resources :placement_reports, only: :index
resources :banners, except: %i[show] do
Expand Down
Loading
Loading