diff --git a/.circleci/config.yml b/.circleci/config.yml index 99795db91..65ceda04c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,7 @@ version: 2.1 orbs: node: circleci/node@6.1.0 + qlty-orb: qltysh/qlty-orb@0.0 defaults: &defaults working_directory: ~/build @@ -89,14 +90,6 @@ jobs: command: | source ~/.rvm/scripts/rvm bundle install - # pnpm install - - - run: - name: Download cc-test-reporter - command: | - mkdir -p ~/tmp - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ~/tmp/cc-test-reporter - chmod +x ~/tmp/cc-test-reporter # Swagger verification - run: @@ -108,10 +101,11 @@ jobs: echo "ERROR: The swagger.json file is not in sync with the yaml specification. Run 'rake swagger:build' and commit 'swagger/swagger.json'." exit 1 fi + mkdir -p ~/tmp curl -L https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.3.0/openapi-generator-cli-6.3.0.jar > ~/tmp/openapi-generator-cli-6.3.0.jar java -jar ~/tmp/openapi-generator-cli-6.3.0.jar validate -i swagger/swagger.json - # we remove the FRONTED_URL from the .env before running the tests + # Configure environment and database - run: name: Database Setup and Configure Environment Variables command: | @@ -149,17 +143,11 @@ jobs: command: pnpm run eslint - run: - name: Run frontend tests + name: Run frontend tests (with coverage) command: | mkdir -p ~/build/coverage/frontend - ~/tmp/cc-test-reporter before-build pnpm run test:coverage - - run: - name: Code Climate Test Coverage (Frontend) - command: | - ~/tmp/cc-test-reporter format-coverage -t lcov -o "~/build/coverage/frontend/codeclimate.frontend_$CIRCLE_NODE_INDEX.json" - # Run backend tests - run: name: Run backend tests @@ -167,18 +155,18 @@ jobs: mkdir -p ~/tmp/test-results/rspec mkdir -p ~/tmp/test-artifacts mkdir -p ~/build/coverage/backend - ~/tmp/cc-test-reporter before-build TESTFILES=$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) - bundle exec rspec --format progress \ + bundle exec rspec -I ./spec --require coverage_helper --require spec_helper --format progress \ --format RspecJunitFormatter \ --out ~/tmp/test-results/rspec.xml \ -- ${TESTFILES} no_output_timeout: 30m - - run: - name: Code Climate Test Coverage (Backend) - command: | - ~/tmp/cc-test-reporter format-coverage -t simplecov -o "~/build/coverage/backend/codeclimate.$CIRCLE_NODE_INDEX.json" + # Qlty coverage publish + - qlty-orb/coverage_publish: + files: | + coverage/coverage.json + coverage/lcov.info - run: name: List coverage directory contents @@ -189,3 +177,7 @@ jobs: root: ~/build paths: - coverage + + - store_artifacts: + path: coverage + destination: coverage diff --git a/Gemfile b/Gemfile index 26d943fa0..927a853a0 100644 --- a/Gemfile +++ b/Gemfile @@ -229,6 +229,7 @@ group :test do gem 'webmock' # test profiling gem 'test-prof' + gem 'simplecov_json_formatter', require: false end group :development, :test do @@ -253,7 +254,7 @@ group :development, :test do gem 'rubocop-factory_bot', require: false gem 'seed_dump' gem 'shoulda-matchers' - gem 'simplecov', '0.17.1', require: false + gem 'simplecov', '>= 0.21', require: false gem 'spring' gem 'spring-watcher-listen' end diff --git a/Gemfile.lock b/Gemfile.lock index b038bbadc..2cce9f322 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,7 +219,7 @@ GEM diff-lcs (1.5.1) digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) - docile (1.4.0) + docile (1.4.1) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (3.1.2) @@ -447,7 +447,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.12.0) + json (2.13.2) json_refs (0.1.8) hana json_schemer (0.2.24) @@ -864,11 +864,12 @@ GEM faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simplecov (0.17.1) + simplecov (0.22.0) docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.13.2) + simplecov_json_formatter (0.1.4) slack-ruby-client (2.5.2) faraday (>= 2.0) faraday-mashify @@ -1093,7 +1094,8 @@ DEPENDENCIES sidekiq (>= 7.3.1) sidekiq-cron (>= 1.12.0) sidekiq_alive - simplecov (= 0.17.1) + simplecov (>= 0.21) + simplecov_json_formatter slack-ruby-client (~> 2.5.2) spring spring-watcher-listen diff --git a/app/helpers/portal_helper.rb b/app/helpers/portal_helper.rb index 3ed303556..e98f0a72d 100644 --- a/app/helpers/portal_helper.rb +++ b/app/helpers/portal_helper.rb @@ -74,6 +74,17 @@ module PortalHelper end end + def generate_portal_brand_url(brand_url, referer) + url = URI.parse(brand_url.to_s) + query_params = Rack::Utils.parse_query(url.query) + query_params['utm_medium'] = 'helpcenter' + query_params['utm_campaign'] = 'branding' + query_params['utm_source'] = URI.parse(referer).host if referer.present? && referer.match?(URI::DEFAULT_PARSER.make_regexp) + + url.query = query_params.to_query + url.to_s + end + def render_category_content(content) ChatwootMarkdownRenderer.new(content).render_markdown_to_plain_text end diff --git a/app/javascript/dashboard/components-next/NewConversation/components/ActionButtons.vue b/app/javascript/dashboard/components-next/NewConversation/components/ActionButtons.vue index 6f2178408..773ebe315 100644 --- a/app/javascript/dashboard/components-next/NewConversation/components/ActionButtons.vue +++ b/app/javascript/dashboard/components-next/NewConversation/components/ActionButtons.vue @@ -11,12 +11,14 @@ import { extractTextFromMarkdown } from 'dashboard/helper/editorHelper'; import Button from 'dashboard/components-next/button/Button.vue'; import WhatsAppOptions from './WhatsAppOptions.vue'; +import ContentTemplateSelector from './ContentTemplateSelector.vue'; const props = defineProps({ attachedFiles: { type: Array, default: () => [] }, isWhatsappInbox: { type: Boolean, default: false }, isEmailOrWebWidgetInbox: { type: Boolean, default: false }, isTwilioSmsInbox: { type: Boolean, default: false }, + isTwilioWhatsAppInbox: { type: Boolean, default: false }, messageTemplates: { type: Array, default: () => [] }, channelType: { type: String, default: '' }, isLoading: { type: Boolean, default: false }, @@ -32,6 +34,7 @@ const emit = defineEmits([ 'discard', 'sendMessage', 'sendWhatsappMessage', + 'sendTwilioMessage', 'insertEmoji', 'addSignature', 'removeSignature', @@ -63,6 +66,20 @@ const sendWithSignature = computed(() => { return fetchSignatureFlagFromUISettings(props.channelType); }); +const showTwilioContentTemplates = computed(() => { + return props.isTwilioWhatsAppInbox && props.inboxId; +}); + +const shouldShowEmojiButton = computed(() => { + return ( + !props.isWhatsappInbox && !props.isTwilioWhatsAppInbox && !props.hasNoInbox + ); +}); + +const isRegularMessageMode = computed(() => { + return !props.isWhatsappInbox && !props.isTwilioWhatsAppInbox; +}); + const setSignature = () => { if (signatureToApply.value) { if (sendWithSignature.value) { @@ -125,7 +142,7 @@ const keyboardEvents = { action: () => { if ( isEditorHotKeyEnabled('enter') && - !props.isWhatsappInbox && + isRegularMessageMode.value && !props.isDropdownActive ) { emit('sendMessage'); @@ -136,7 +153,7 @@ const keyboardEvents = { action: () => { if ( isEditorHotKeyEnabled('cmd_enter') && - !props.isWhatsappInbox && + isRegularMessageMode.value && !props.isDropdownActive ) { emit('sendMessage'); @@ -158,8 +175,13 @@ useKeyboardEvents(keyboardEvents); :message-templates="messageTemplates" @send-message="emit('sendWhatsappMessage', $event)" /> +
@@ -172,7 +194,7 @@ useKeyboardEvents(keyboardEvents); />
@@ -199,7 +221,7 @@ useKeyboardEvents(keyboardEvents); />