Skip to content

Commit

Permalink
Feature basic chatwoot integration (#13)
Browse files Browse the repository at this point in the history
* Continue integration..

* Fix chatwoot create flow

* Init embedding view

* Embedding continue implementation

* Authentication flow

* Frontend init

* Improve embeding layout

* Backend search, create and show contact

* Remove duplicate code and UI improves

* css code improves

* Remove unecessary codes and improves authenticate flow
  • Loading branch information
douglara committed Jul 31, 2023
1 parent ad88f56 commit dec5f4f
Show file tree
Hide file tree
Showing 28 changed files with 647 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
web: bin/rails server -p 3000
web: bin/rails server -p 3001
css: bin/rails tailwindcss:watch
1 change: 1 addition & 0 deletions app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_directory ../stylesheets/components .css

// vendor/theme
//= link_directory ../../../vendor/theme
Expand Down
9 changes: 9 additions & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
@import "stisla/src/scss/components";
@import "stisla/node_modules/izitoast/dist/css/iziToast";
@import "./actiontext.scss";
@import "./commons/w-btn-outline.scss";
@import "./commons/w-btn-block.scss";

.btn-remove {
font-size: 12px;
Expand All @@ -17,4 +19,11 @@
color: #fff;
max-height: 30px;
margin-left: 15px;
}

.embed {
.main-content {
padding-top: 0px !important;
}
background-color: #F6F8FE;
}
10 changes: 10 additions & 0 deletions app/assets/stylesheets/commons/w-btn-block.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.w-btn-block {
color: #888599 !important;
border-radius: 5px;
border: 1.8px solid #F2F1F7;
padding: 10px !important;
i {
font-size: 15px !important;
margin: 0px !important;
}
}
17 changes: 17 additions & 0 deletions app/assets/stylesheets/commons/w-btn-outline.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.w-btn-outline {
font-weight: 600;
font-size: 12px;
line-height: 30px;
padding: 0.3rem 0.8rem;
letter-spacing: .5px;

color: #6857D9;
background-color: #FFFFFF;
border: 1.5px solid #F2F1F7;
border-radius: 5px;
}

.w-btn-outline:hover {
border-radius: 5px;
border: 1.5px solid #D9DEFF;
}
37 changes: 37 additions & 0 deletions app/assets/stylesheets/components/chatwoot_embed.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.component-chatwoot-embed{
padding: 32px;
background-color: #F6F8FE;
p {
margin-bottom: 0px;
}

input[disabled] {
background-color: #FFF;
}
button {
background: none !important;
}

.btn-clock {
border-radius: 5px;
border: 1.5px solid #FBE0D8;
background: #FAEEEB;
color: #CF4F27;
padding-left: 5px;
padding-right: 5px;
svg {
height: 16px;
}
}

.custom-btn-user {
color: #888599 !important;
border-radius: 5px;
border: 1.8px solid #F2F1F7;
padding: 10px !important;
i {
font-size: 15px !important;
margin: 0px !important;
}
}
}
30 changes: 23 additions & 7 deletions app/controllers/accounts/apps/chatwoots_controller.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
class Accounts::Apps::ChatwootsController < InternalController
before_action :set_chatwoot, only: %i[ edit disable new_connection pair_qr_code new_connection_status ]
before_action :set_chatwoot, only: %i[ edit update destroy ]

def new
current_user.account.apps_chatwoots.create(
account: current_user.account
) if current_user.account.apps_chatwoots.blank?

redirect_to edit_account_apps_chatwoot_path(current_user.account, current_user.account.apps_chatwoots.first)
if current_user.account.apps_chatwoots.blank?
@chatwoot = current_user.account.apps_chatwoots.new
else
redirect_to edit_account_apps_chatwoot_path(current_user.account, current_user.account.apps_chatwoots.first)
end
end

def edit
end

def create
@chatwoot = current_user.account.apps_chatwoots.build(chatwoot_params)
if @chatwoot.save
redirect_to edit_account_apps_chatwoot_path(current_user.account, @chatwoot)
else
render :new
end
end

def destroy
@chatwoot.destroy
redirect_to account_settings_path(current_user.account)
end

def update
@chatwoot.update(chatwoot_params)
redirect_to edit_account_apps_chatwoot_path(current_user.account, current_user.account.apps_chatwoots.first)
end

private
Expand All @@ -21,6 +37,6 @@ def set_chatwoot
end

def chatwoot_params
params.require(:apps_chatwoot).permit(:endpoint_url, :user_token)
params.require(:apps_chatwoot).permit(:chatwoot_endpoint_url, :chatwoot_account_id, :chatwoot_user_token, :active)
end
end
78 changes: 78 additions & 0 deletions app/controllers/accounts/contacts/chatwoot_embed_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class Accounts::Contacts::ChatwootEmbedController < InternalController
layout "embed"
before_action :set_contact, only: %i[ show ]

def search
contact = contact_search

if contact.present?
redirect_to account_chatwoot_embed_path(current_user.account, contact)
else
redirect_to new_account_chatwoot_embed_path(current_user.account, chatwoot_contact: params['chatwoot_contact'])
end
end

def show
end

def new
chatwoot_contact = JSON.parse(params['chatwoot_contact'])
@contact = current_user.account.contacts.new({
full_name: chatwoot_contact['name'],
email: chatwoot_contact['email'],
phone: chatwoot_contact['phone_number'],
additional_attributes: {'chatwoot_id': chatwoot_contact['id']}
})
end

def create
@contact = current_user.account.contacts.new(contact_params)

if @contact.save
redirect_to account_chatwoot_embed_path(current_user.account, @contact), notice: "Contact was successfully created."
else
render :new, status: :unprocessable_entity
end
end

private
def set_contact
@contact = Contact.find(params[:id])
end

def contact_params
params.require(:contact).permit(:full_name, :phone, :email, additional_attributes: {})
end

def chatwoot_contact
@chatwoot_contact ||= JSON.parse(params['chatwoot_contact'])
end

def contact_search()
if chatwoot_contact['email'].present? && chatwoot_contact['phone_number'].present?
return current_user.account.contacts.where(
":chatwoot_id <@ additional_attributes OR email LIKE :email OR phone LIKE :phone",
chatwoot_id: { chatwoot_id: "#{chatwoot_contact['id']}" }.to_json,
email: "#{chatwoot_contact['email']}",
phone: "#{chatwoot_contact['phone_number']}"
).first
elsif chatwoot_contact['email'].present?
return current_user.account.contacts.where(
":chatwoot_id <@ additional_attributes OR email LIKE :email",
chatwoot_id: { chatwoot_id: "#{chatwoot_contact['id']}" }.to_json,
email: "#{chatwoot_contact['email']}"
).first
elsif chatwoot_contact['phone_number'].present?
return current_user.account.contacts.where(
":chatwoot_id <@ additional_attributes OR phone LIKE :phone",
chatwoot_id: { chatwoot_id: "#{chatwoot_contact['id']}" }.to_json,
phone: "#{chatwoot_contact['phone_number']}"
).first
else
return current_user.account.contacts.where(
":chatwoot_id <@ additional_attributes",
chatwoot_id: { chatwoot_id: "#{chatwoot_contact['id']}" }.to_json
).first
end
end
end
40 changes: 40 additions & 0 deletions app/controllers/apps/chatwoots_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class Apps::ChatwootsController < ActionController::Base
before_action :load_chatwoot, execpt: :webhooks
before_action :authenticate_by_token, if: -> { current_user.blank? }
skip_before_action :verify_authenticity_token, execpt: :embedding
layout "embed"

def webhooks
render json: { ok: true }, status: 200
end

def embedding
end

def embedding_init_authenticate
@token = params['token']
end

def embedding_authenticate
event = JSON.parse(params['event'])
user_email = event['data']['currentAgent']['email']
user = User.find_by(email: user_email, account_id: @chatwoot.account_id)
return render plain: "User not found", status: 400 if user.blank?
sign_in(user)
redirect_to embedding_apps_chatwoots_path()
end

private

def authenticate_by_token
if @chatwoot.present? && action_name == 'embedding'
redirect_to embedding_init_authenticate_apps_chatwoots_path(token: params['token']) if action_name != 'embedding_authenticate'
else
render plain: "Unauthorized", status: 400 if @chatwoot.blank?
end
end

def load_chatwoot
@chatwoot = Apps::Chatwoot.find_by(embedding_token: params['token'])
end
end
2 changes: 2 additions & 0 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "@hotwired/turbo-rails"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "controllers"
import lucide from "lucide/dist/umd/lucide"

Rails.start()
ActiveStorage.start()
Expand All @@ -19,6 +20,7 @@ require("@nathanvda/cocoon")
require("./stisla_scripts")

$(document).on("turbo:load", () => {
lucide.createIcons();
// Daterangepicker
if(jQuery().daterangepicker) {
if($(".datetimepicker").length) {
Expand Down
Loading

0 comments on commit dec5f4f

Please sign in to comment.