Skip to content

Commit

Permalink
Merge branch 'release/1.18.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sojan-official committed Jul 15, 2021
2 parents 0a96ded + fa3cc40 commit 9de36f2
Show file tree
Hide file tree
Showing 687 changed files with 12,307 additions and 1,560 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -7,7 +7,7 @@ defaults: &defaults
working_directory: ~/build
docker:
# specify the version you desire here
- image: circleci/ruby:2.7.2-node-browsers
- image: circleci/ruby:2.7.3-node-browsers

# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
Expand Down
3 changes: 1 addition & 2 deletions .codeclimate.yml
Expand Up @@ -30,6 +30,5 @@ exclude_patterns:
- "**/*.md"
- "**/*.yml"
- "app/javascript/dashboard/i18n/locale"
- "stories/**/*"
- "**/*.stories.js"
- "**/stories/"
- "stories/"
51 changes: 4 additions & 47 deletions .devcontainer/Dockerfile
@@ -1,51 +1,8 @@
# pre-build stage
ARG VARIANT=2.7
FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}

# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user.
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
groupmod --gid $USER_GID vscode \
&& usermod --uid $USER_UID --gid $USER_GID vscode \
&& chmod -R $USER_UID:$USER_GID /home/vscode; \
fi

# [Option] Install Node.js
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi


# tmux is for overmind
# TODO : install foreman in future
# packages: postgresql-server-dev-all
# may be postgres in same machine

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends \
libssl-dev \
tar \
tzdata \
postgresql-client \
yarn \
git \
imagemagick \
tmux \
zsh

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

# The below image is created out of the Dockerfile.base
# It has the dependencies already installed so that codespace will boot up fast
FROM ghcr.io/chatwoot/chatwoot_codespace:latest

# Do the set up required for chatwoot app
WORKDIR /workspace
COPY . /workspace

# TODO: figure out installing rvm
# RUN rvm install
COPY Gemfile Gemfile.lock ./
RUN gem install bundler
RUN bundle install
COPY package.json yarn.lock ./
RUN yarn install
RUN yarn && gem install bundler && bundle install
45 changes: 45 additions & 0 deletions .devcontainer/Dockerfile.base
@@ -0,0 +1,45 @@
# pre-build stage
ARG VARIANT=2.7
FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}

# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user.
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
groupmod --gid $USER_GID vscode \
&& usermod --uid $USER_UID --gid $USER_GID vscode \
&& chmod -R $USER_UID:$USER_GID /home/vscode; \
fi

# [Option] Install Node.js
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends \
libssl-dev \
tar \
tzdata \
postgresql-client \
yarn \
git \
imagemagick \
tmux \
zsh


# Install overmind
RUN curl -L https://github.com/DarthSim/overmind/releases/download/v2.1.0/overmind-v2.1.0-linux-amd64.gz > overmind.gz \
&& gunzip overmind.gz \
&& sudo mv overmind /usr/local/bin \
&& chmod +x /usr/local/bin/overmind

# Do the set up required for chatwoot app
WORKDIR /workspace
COPY . /workspace
RUN yarn

COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install

24 changes: 15 additions & 9 deletions .devcontainer/devcontainer.json
Expand Up @@ -12,22 +12,28 @@
"extensions": [
"rebornix.Ruby",
"misogi.ruby-rubocop",
"wingrunr21.vscode-ruby"
"wingrunr21.vscode-ruby",
"davidpallinder.rails-test-runner",
"eamodio.gitlens",
"github.copilot",
"mrmlnc.vscode-duplicate"
],


// TODO: figure whether we can get all this ports work properly

// 3000 rails
// 3035 webpacker
// 5432 postgres
// 6379 redis
// 1025,8025 mailhog
"forwardPorts": [5432, 6379, 1025, 8025],
"forwardPorts": [8025],
//your application may need to listen on all interfaces (0.0.0.0) not just localhost for it to be available externally. Defaults to []
"appPort": [3000, 3035],

// Use 'postCreateCommand' to run commands after the container is created.
// #TODO: can we move logic of copy env file into dockerfile ?
"postCreateCommand": "cp .env.example .env",
"postCreateCommand": ".devcontainer/scripts/setup.sh && bundle exec rake db:chatwoot_prepare && yarn",
"portsAttributes": {
"3000": {
"label": "Rails Server"
},
"8025": {
"label": "Mailhog UI"
}
},
}
8 changes: 8 additions & 0 deletions .devcontainer/scripts/setup.sh
@@ -0,0 +1,8 @@
cp .env.example .env
sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env
sed -i -e '/SMTP_ADDRESS/ s/=.*/=localhost/' .env
sed -i -e "/FRONTEND_URL/ s/=.*/=https:\/\/$CODESPACE_NAME-3000.githubpreview.dev/" .env
sed -i -e "/WEBPACKER_DEV_SERVER_PUBLIC/ s/=.*/=https:\/\/$CODESPACE_NAME-3035.githubpreview.dev/" .env
# uncomment the webpacker env variable
sed -i -e '/WEBPACKER_DEV_SERVER_PUBLIC/s/^# //' .env
2 changes: 2 additions & 0 deletions .env.example
Expand Up @@ -155,3 +155,5 @@ USE_INBOX_AVATAR_FOR_BOT=true
## Development Only Config
# if you want to use letter_opener for local emails
# LETTER_OPENER=true
# meant to be used in github codespaces
# WEBPACKER_DEV_SERVER_PUBLIC=
23 changes: 23 additions & 0 deletions .github/workflows/publish_codespace_image.yml
@@ -0,0 +1,23 @@
name: Publish Codespace Base Image

on:
workflow_dispatch:

jobs:
publish-code-space-image:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build the Codespace Base Image
run: |
docker build . -t ghcr.io/chatwoot/chatwoot_codespace:latest -f .devcontainer/Dockerfile.base
docker push ghcr.io/chatwoot/chatwoot_codespace:latest
2 changes: 1 addition & 1 deletion .ruby-version
@@ -1 +1 @@
2.7.2
2.7.3
2 changes: 2 additions & 0 deletions .storybook/preview.js
Expand Up @@ -3,6 +3,7 @@ import Vue from 'vue';
import Vuex from 'vuex';
import VueI18n from 'vue-i18n';
import Vuelidate from 'vuelidate';
import Multiselect from 'vue-multiselect';

import WootUiKit from '../app/javascript/dashboard/components';
import i18n from '../app/javascript/dashboard/i18n';
Expand All @@ -13,6 +14,7 @@ Vue.use(VueI18n);
Vue.use(Vuelidate);
Vue.use(WootUiKit);
Vue.use(Vuex);
Vue.component('multiselect', Multiselect);

const store = new Vuex.Store({});
const i18nConfig = new VueI18n({
Expand Down
3 changes: 2 additions & 1 deletion Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'

ruby '2.7.2'
ruby '2.7.3'

##-- base gems for rails --##
gem 'rack-cors', require: 'rack/cors'
Expand Down Expand Up @@ -53,6 +53,7 @@ gem 'activerecord-import'
gem 'dotenv-rails'
gem 'foreman'
gem 'puma'
gem 'rack-timeout'
gem 'webpacker', '~> 5.x'
# metrics on heroku
gem 'barnes'
Expand Down
6 changes: 4 additions & 2 deletions Gemfile.lock
Expand Up @@ -75,7 +75,7 @@ GEM
zeitwerk (~> 2.2, >= 2.2.2)
acts-as-taggable-on (6.5.0)
activerecord (>= 5.0, < 6.1)
addressable (2.7.0)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
administrate (0.16.0)
actionpack (>= 5.0)
Expand Down Expand Up @@ -384,6 +384,7 @@ GEM
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.6.0)
rails (6.0.3.7)
actioncable (= 6.0.3.7)
actionmailbox (= 6.0.3.7)
Expand Down Expand Up @@ -666,6 +667,7 @@ DEPENDENCIES
puma
pundit
rack-cors
rack-timeout
rails
redis
redis-namespace
Expand Down Expand Up @@ -704,7 +706,7 @@ DEPENDENCIES
wisper (= 2.0.0)

RUBY VERSION
ruby 2.7.2p137
ruby 2.7.3p183

BUNDLED WITH
2.1.4
4 changes: 4 additions & 0 deletions app/actions/contact_merge_action.rb
Expand Up @@ -2,6 +2,10 @@ class ContactMergeAction
pattr_initialize [:account!, :base_contact!, :mergee_contact!]

def perform
# This case happens when an agent updates a contact email in dashboard,
# while the contact also update his email via email collect box
return @base_contact if base_contact.id == mergee_contact.id

ActiveRecord::Base.transaction do
validate_contacts
merge_conversations
Expand Down
28 changes: 28 additions & 0 deletions app/builders/csat_surveys/response_builder.rb
@@ -0,0 +1,28 @@
class CsatSurveys::ResponseBuilder
pattr_initialize [:message]

def perform
raise 'Invalid Message' unless message.input_csat?

conversation = message.conversation
rating = message.content_attributes.dig('submitted_values', 'csat_survey_response', 'rating')
feedback_message = message.content_attributes.dig('submitted_values', 'csat_survey_response', 'feedback_message')

return if rating.blank?

process_csat_response(conversation, rating, feedback_message)
end

private

def process_csat_response(conversation, rating, feedback_message)
csat_survey_response = message.csat_survey_response || CsatSurveyResponse.new(
message_id: message.id, account_id: message.account_id, conversation_id: message.conversation_id,
contact_id: conversation.contact_id, assigned_agent: conversation.assignee
)
csat_survey_response.rating = rating
csat_survey_response.feedback_message = feedback_message
csat_survey_response.save!
csat_survey_response
end
end
12 changes: 1 addition & 11 deletions app/builders/v2/report_builder.rb
@@ -1,4 +1,5 @@
class V2::ReportBuilder
include DateRangeHelper
attr_reader :account, :params

def initialize(account, params)
Expand Down Expand Up @@ -83,10 +84,6 @@ def avg_resolution_time
.average(:value)
end

def range
parse_date_time(params[:since])..parse_date_time(params[:until])
end

# Taking average of average is not too accurate
# https://en.wikipedia.org/wiki/Simpson's_paradox
# TODO: Will optimize this later
Expand All @@ -101,11 +98,4 @@ def avg_first_response_time_summary

(avg_first_response_time.values.sum / avg_first_response_time.values.length)
end

def parse_date_time(datetime)
return datetime if datetime.is_a?(DateTime)
return datetime.to_datetime if datetime.is_a?(Time) || datetime.is_a?(Date)

DateTime.strptime(datetime, '%s')
end
end
3 changes: 2 additions & 1 deletion app/controllers/api/v1/accounts/campaigns_controller.rb
Expand Up @@ -28,6 +28,7 @@ def campaign
end

def campaign_params
params.require(:campaign).permit(:title, :description, :message, :enabled, :inbox_id, :sender_id, trigger_rules: {})
params.require(:campaign).permit(:title, :description, :message, :enabled, :inbox_id, :sender_id,
:scheduled_at, audience: [:type, :id], trigger_rules: {})
end
end
18 changes: 11 additions & 7 deletions app/controllers/api/v1/accounts/contacts_controller.rb
Expand Up @@ -7,15 +7,14 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
sort_on :last_activity_at, type: :datetime

RESULTS_PER_PAGE = 15
protect_from_forgery with: :null_session

before_action :check_authorization
before_action :set_current_page, only: [:index, :active, :search]
before_action :fetch_contact, only: [:show, :update, :contactable_inboxes]

def index
@contacts_count = resolved_contacts.count
@contacts = fetch_contact_last_seen_at(resolved_contacts)
@contacts = fetch_contacts_with_conversation_count(resolved_contacts)
end

def search
Expand All @@ -26,7 +25,7 @@ def search
search: "%#{params[:q]}%"
)
@contacts_count = contacts.count
@contacts = fetch_contact_last_seen_at(contacts)
@contacts = fetch_contacts_with_conversation_count(contacts)
end

def import
Expand Down Expand Up @@ -72,17 +71,22 @@ def update

private

# TODO: Move this to a finder class
def resolved_contacts
@resolved_contacts ||= Current.account.contacts
.where.not(email: [nil, ''])
.or(Current.account.contacts.where.not(phone_number: [nil, '']))
return @resolved_contacts if @resolved_contacts

@resolved_contacts = Current.account.contacts
.where.not(email: [nil, ''])
.or(Current.account.contacts.where.not(phone_number: [nil, '']))
@resolved_contacts = @resolved_contacts.tagged_with(params[:labels], any: true) if params[:labels].present?
@resolved_contacts
end

def set_current_page
@current_page = params[:page] || 1
end

def fetch_contact_last_seen_at(contacts)
def fetch_contacts_with_conversation_count(contacts)
filtrate(contacts).left_outer_joins(:conversations)
.select('contacts.*, COUNT(conversations.id) as conversations_count')
.group('contacts.id')
Expand Down

0 comments on commit 9de36f2

Please sign in to comment.