diff --git a/.circleci/config.yml b/.circleci/config.yml index 459faf1c8..b8a628677 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,7 +74,7 @@ jobs: source ~/.rvm/scripts/rvm rvm install "3.3.3" rvm use 3.3.3 --default - gem install bundler + gem install bundler -v 2.5.16 - run: name: Install Application Dependencies diff --git a/.codeclimate.yml b/.codeclimate.yml index 5e16262da..213f7d172 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -57,3 +57,5 @@ exclude_patterns: - 'app/javascript/shared/constants/locales.js' - 'app/javascript/dashboard/helper/specs/macrosFixtures.js' - 'app/javascript/dashboard/routes/dashboard/settings/macros/constants.js' + - '**/fixtures/**' + - '**/*/fixtures.js' diff --git a/.github/workflows/publish_foss_docker.yml b/.github/workflows/publish_foss_docker.yml index d48b82a58..732b22a28 100644 --- a/.github/workflows/publish_foss_docker.yml +++ b/.github/workflows/publish_foss_docker.yml @@ -12,6 +12,7 @@ on: - master tags: - v* +# pull_request: workflow_dispatch: jobs: @@ -40,7 +41,9 @@ jobs: - name: set docker tag run: | - echo "DOCKER_TAG=chatwoot/chatwoot:$GIT_REF-ce" >> $GITHUB_ENV + # Replace forward slashes with hyphens in the ref name + SANITIZED_REF=$(echo "$GIT_REF" | sed 's/\//-/g') + echo "DOCKER_TAG=chatwoot/chatwoot:$SANITIZED_REF-ce" >> $GITHUB_ENV - name: replace docker tag if master if: github.ref_name == 'master' @@ -48,6 +51,7 @@ jobs: echo "DOCKER_TAG=chatwoot/chatwoot:latest-ce" >> $GITHUB_ENV - name: Login to DockerHub + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -58,6 +62,6 @@ jobs: with: context: . file: docker/Dockerfile - platforms: linux/amd64 - push: true + platforms: linux/amd64, linux/arm64 + push: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} tags: ${{ env.DOCKER_TAG }} diff --git a/Gemfile b/Gemfile index f18305970..439b0f63e 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem 'aws-sdk-s3', require: false # original gem isn't maintained actively # we wanted updated version of faraday which is a dependency for slack-ruby-client gem 'azure-storage-blob', git: 'https://github.com/chatwoot/azure-storage-ruby', branch: 'chatwoot', require: false -gem 'google-cloud-storage', require: false +gem 'google-cloud-storage', '>= 1.48.0', require: false gem 'image_processing' ##-- gems for database --# diff --git a/Gemfile.lock b/Gemfile.lock index e2f5c91be..74cdbeea8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -33,70 +33,70 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.0.8.5) - actionpack (= 7.0.8.5) - activesupport (= 7.0.8.5) + actioncable (7.0.8.7) + actionpack (= 7.0.8.7) + activesupport (= 7.0.8.7) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8.5) - actionpack (= 7.0.8.5) - activejob (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionmailbox (7.0.8.7) + actionpack (= 7.0.8.7) + activejob (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.8.5) - actionpack (= 7.0.8.5) - actionview (= 7.0.8.5) - activejob (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionmailer (7.0.8.7) + actionpack (= 7.0.8.7) + actionview (= 7.0.8.7) + activejob (= 7.0.8.7) + activesupport (= 7.0.8.7) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) - actionpack (7.0.8.5) - actionview (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionpack (7.0.8.7) + actionview (= 7.0.8.7) + activesupport (= 7.0.8.7) rack (~> 2.0, >= 2.2.4) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.8.5) - actionpack (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + actiontext (7.0.8.7) + actionpack (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8.5) - activesupport (= 7.0.8.5) + actionview (7.0.8.7) + activesupport (= 7.0.8.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) active_record_query_trace (1.8) - activejob (7.0.8.5) - activesupport (= 7.0.8.5) + activejob (7.0.8.7) + activesupport (= 7.0.8.7) globalid (>= 0.3.6) - activemodel (7.0.8.5) - activesupport (= 7.0.8.5) - activerecord (7.0.8.5) - activemodel (= 7.0.8.5) - activesupport (= 7.0.8.5) + activemodel (7.0.8.7) + activesupport (= 7.0.8.7) + activerecord (7.0.8.7) + activemodel (= 7.0.8.7) + activesupport (= 7.0.8.7) activerecord-import (1.4.1) activerecord (>= 4.2) - activestorage (7.0.8.5) - actionpack (= 7.0.8.5) - activejob (= 7.0.8.5) - activerecord (= 7.0.8.5) - activesupport (= 7.0.8.5) + activestorage (7.0.8.7) + actionpack (= 7.0.8.7) + activejob (= 7.0.8.7) + activerecord (= 7.0.8.7) + activesupport (= 7.0.8.7) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.8.5) + activesupport (7.0.8.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -209,7 +209,7 @@ GEM devise (> 3.5.2, < 5) rails (>= 4.2.0, < 7.2) diff-lcs (1.5.1) - digest-crc (0.6.4) + digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) docile (1.4.0) domain_name (0.5.20190701) @@ -284,39 +284,39 @@ GEM activesupport (>= 6.1) gmail_xoauth (0.4.3) oauth (>= 0.3.6) - google-apis-core (0.11.0) + google-apis-core (0.15.1) addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) + googleauth (~> 1.9) + httpclient (>= 2.8.3, < 3.a) mini_mime (~> 1.0) + mutex_m representable (~> 3.0) retriable (>= 2.0, < 4.a) - rexml - webrick - google-apis-iamcredentials_v1 (0.17.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.19.0) - google-apis-core (>= 0.9.0, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-apis-iamcredentials_v1 (0.22.0) + google-apis-core (>= 0.15.0, < 2.a) + google-apis-storage_v1 (0.47.0) + google-apis-core (>= 0.15.0, < 2.a) + google-cloud-core (1.7.1) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-dialogflow-v2 (0.31.0) gapic-common (>= 0.20.0, < 2.a) google-cloud-errors (~> 1.0) google-cloud-location (>= 0.4, < 2.a) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) + google-cloud-env (2.2.1) + faraday (>= 1.0, < 3.a) google-cloud-errors (1.3.1) google-cloud-location (0.6.0) gapic-common (>= 0.20.0, < 2.a) google-cloud-errors (~> 1.0) - google-cloud-storage (1.44.0) + google-cloud-storage (1.52.0) addressable (~> 2.8) digest-crc (~> 0.4) - google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.19.0) + google-apis-core (~> 0.13) + google-apis-iamcredentials_v1 (~> 0.18) + google-apis-storage_v1 (~> 0.38) google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) + googleauth (~> 1.9) mini_mime (~> 1.0) google-cloud-translate-v3 (0.10.0) gapic-common (>= 0.20.0, < 2.a) @@ -331,10 +331,10 @@ GEM grpc (~> 1.41) googleapis-common-protos-types (1.14.0) google-protobuf (~> 3.18) - googleauth (1.5.2) - faraday (>= 0.17.3, < 3.a) + googleauth (1.11.2) + faraday (>= 1.0, < 3.a) + google-cloud-env (~> 2.1) jwt (>= 1.4, < 3.0) - memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) @@ -452,7 +452,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.22.0) + loofah (2.23.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -462,7 +462,6 @@ GEM net-smtp marcel (1.0.4) maxminddb (0.1.22) - memoist (0.16.2) meta_request (0.8.3) rack-contrib (>= 1.1, < 3) railties (>= 3.0.0, < 8) @@ -472,14 +471,15 @@ GEM mime-types-data (3.2023.0218.1) mini_magick (4.12.0) mini_mime (1.1.5) - mini_portile2 (2.8.7) - minitest (5.25.1) + mini_portile2 (2.8.8) + minitest (5.25.4) mock_redis (0.36.0) ruby2_keywords msgpack (1.7.0) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.3.0) + mutex_m (0.3.0) neighbor (0.2.3) activerecord (>= 5.2) net-http (0.4.1) @@ -502,14 +502,14 @@ GEM newrelic_rpm (9.6.0) base64 nio4r (2.7.3) - nokogiri (1.16.7) + nokogiri (1.17.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.16.7-arm64-darwin) + nokogiri (1.17.1-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.7-x86_64-darwin) + nokogiri (1.17.1-x86_64-darwin) racc (~> 1.4) - nokogiri (1.16.7-x86_64-linux) + nokogiri (1.17.1-x86_64-linux) racc (~> 1.4) oauth (1.1.0) oauth-tty (~> 1.0, >= 1.0.1) @@ -581,30 +581,30 @@ GEM rack-test (2.1.0) rack (>= 1.3) rack-timeout (0.6.3) - rails (7.0.8.5) - actioncable (= 7.0.8.5) - actionmailbox (= 7.0.8.5) - actionmailer (= 7.0.8.5) - actionpack (= 7.0.8.5) - actiontext (= 7.0.8.5) - actionview (= 7.0.8.5) - activejob (= 7.0.8.5) - activemodel (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + rails (7.0.8.7) + actioncable (= 7.0.8.7) + actionmailbox (= 7.0.8.7) + actionmailer (= 7.0.8.7) + actionpack (= 7.0.8.7) + actiontext (= 7.0.8.7) + actionview (= 7.0.8.7) + activejob (= 7.0.8.7) + activemodel (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) bundler (>= 1.15.0) - railties (= 7.0.8.5) + railties (= 7.0.8.7) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.1) loofah (~> 2.21) - nokogiri (~> 1.14) - railties (7.0.8.5) - actionpack (= 7.0.8.5) - activesupport (= 7.0.8.5) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (7.0.8.7) + actionpack (= 7.0.8.7) + activesupport (= 7.0.8.7) method_source rake (>= 12.2) thor (~> 1.0) @@ -824,7 +824,6 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.8.2) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -886,7 +885,7 @@ DEPENDENCIES geocoder gmail_xoauth google-cloud-dialogflow-v2 (>= 0.24.0) - google-cloud-storage + google-cloud-storage (>= 1.48.0) google-cloud-translate-v3 (>= 0.7.0) groupdate grpc diff --git a/app.json b/app.json index d50040814..08e725c8e 100644 --- a/app.json +++ b/app.json @@ -48,7 +48,7 @@ "size": "basic" } }, - "stack": "heroku-20", + "stack": "heroku-24", "image": "heroku/ruby", "addons": [ { @@ -58,7 +58,7 @@ "plan": "heroku-postgresql:essential-0" } ], - "stack": "heroku-20", + "stack": "heroku-24", "buildpacks": [ { "url": "heroku/nodejs" diff --git a/app/controllers/api/v1/accounts/contacts_controller.rb b/app/controllers/api/v1/accounts/contacts_controller.rb index 250c64a86..0e024b3d8 100644 --- a/app/controllers/api/v1/accounts/contacts_controller.rb +++ b/app/controllers/api/v1/accounts/contacts_controller.rb @@ -14,7 +14,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController before_action :check_authorization before_action :set_current_page, only: [:index, :active, :search, :filter] before_action :fetch_contact, only: [:show, :update, :destroy, :avatar, :contactable_inboxes, :destroy_custom_attributes] - before_action :set_include_contact_inboxes, only: [:index, :search, :filter] + before_action :set_include_contact_inboxes, only: [:index, :search, :filter, :show, :update] def index @contacts_count = resolved_contacts.count @@ -68,6 +68,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController @contacts = fetch_contacts(contacts) rescue CustomExceptions::CustomFilter::InvalidAttribute, CustomExceptions::CustomFilter::InvalidOperator, + CustomExceptions::CustomFilter::InvalidQueryOperator, CustomExceptions::CustomFilter::InvalidValue => e render_could_not_create_error(e.message) end diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 2aedf1928..2cd5281ff 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -46,6 +46,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro @conversations_count = result[:count] rescue CustomExceptions::CustomFilter::InvalidAttribute, CustomExceptions::CustomFilter::InvalidOperator, + CustomExceptions::CustomFilter::InvalidQueryOperator, CustomExceptions::CustomFilter::InvalidValue => e render_could_not_create_error(e.message) end diff --git a/app/controllers/api/v1/accounts/integrations/captain_controller.rb b/app/controllers/api/v1/accounts/integrations/captain_controller.rb index 15e81b726..6813d14b5 100644 --- a/app/controllers/api/v1/accounts/integrations/captain_controller.rb +++ b/app/controllers/api/v1/accounts/integrations/captain_controller.rb @@ -2,10 +2,22 @@ class Api::V1::Accounts::Integrations::CaptainController < Api::V1::Accounts::Ba before_action :hook def proxy + request_url = build_request_url(request_path) response = HTTParty.send(request_method, request_url, body: permitted_params[:body].to_json, headers: headers) render plain: response.body, status: response.code end + def copilot + request_url = build_request_url(build_request_path("/assistants/#{hook.settings['assistant_id']}/copilot")) + params = { + previous_messages: copilot_params[:previous_messages], + conversation_history: conversation_history, + message: copilot_params[:message] + } + response = HTTParty.send(:post, request_url, body: params.to_json, headers: headers) + render plain: response.body, status: response.code + end + private def headers @@ -17,15 +29,19 @@ class Api::V1::Accounts::Integrations::CaptainController < Api::V1::Accounts::Ba } end + def build_request_path(route) + "api/accounts/#{hook.settings['account_id']}#{route}" + end + def request_path request_route = with_leading_hash_on_route(params[:route]) return 'api/sessions/profile' if request_route == '/sessions/profile' - "api/accounts/#{hook.settings['account_id']}#{request_route}" + build_request_path(request_route) end - def request_url + def build_request_url(request_path) base_url = InstallationConfig.find_by(name: 'CAPTAIN_API_URL').value URI.join(base_url, request_path).to_s end @@ -47,6 +63,15 @@ class Api::V1::Accounts::Integrations::CaptainController < Api::V1::Accounts::Ba request_route.start_with?('/') ? request_route : "/#{request_route}" end + def conversation_history + conversation = Current.account.conversations.find_by!(display_id: copilot_params[:conversation_id]) + conversation.to_llm_text + end + + def copilot_params + params.permit(:previous_messages, :conversation_id, :message) + end + def permitted_params params.permit(:method, :route, body: {}) end diff --git a/app/controllers/api/v1/profiles_controller.rb b/app/controllers/api/v1/profiles_controller.rb index bd3c2673c..ae1a1fe30 100644 --- a/app/controllers/api/v1/profiles_controller.rb +++ b/app/controllers/api/v1/profiles_controller.rb @@ -17,7 +17,7 @@ class Api::V1::ProfilesController < Api::BaseController def avatar @user.avatar.attachment.destroy! if @user.avatar.attached? - head :ok + @user.reload end def auto_offline diff --git a/app/controllers/platform/api/v1/accounts_controller.rb b/app/controllers/platform/api/v1/accounts_controller.rb index 9e6d53fef..e11cf9d4a 100644 --- a/app/controllers/platform/api/v1/accounts_controller.rb +++ b/app/controllers/platform/api/v1/accounts_controller.rb @@ -4,6 +4,7 @@ class Platform::Api::V1::AccountsController < PlatformController def create @resource = Account.create!(account_params) update_resource_features + @resource.save! @platform_app.platform_app_permissibles.find_or_create_by(permissible: @resource) end diff --git a/app/dashboards/account_dashboard.rb b/app/dashboards/account_dashboard.rb index de6ab42bb..b566551f4 100644 --- a/app/dashboards/account_dashboard.rb +++ b/app/dashboards/account_dashboard.rb @@ -26,7 +26,8 @@ class AccountDashboard < Administrate::BaseDashboard conversations: CountField, locale: Field::Select.with_options(collection: LANGUAGES_CONFIG.map { |_x, y| y[:iso_639_1_code] }), status: Field::Select.with_options(collection: [%w[Active active], %w[Suspended suspended]]), - account_users: Field::HasMany + account_users: Field::HasMany, + custom_attributes: Field::String }.merge(enterprise_attribute_types).freeze # COLLECTION_ATTRIBUTES @@ -45,7 +46,7 @@ class AccountDashboard < Administrate::BaseDashboard # SHOW_PAGE_ATTRIBUTES # an array of attributes that will be displayed on the model's show page. - enterprise_show_page_attributes = ChatwootApp.enterprise? ? %i[limits all_features] : [] + enterprise_show_page_attributes = ChatwootApp.enterprise? ? %i[custom_attributes limits all_features] : [] SHOW_PAGE_ATTRIBUTES = (%i[ id name diff --git a/app/helpers/filter_helper.rb b/app/helpers/filter_helper.rb index bce2de5ea..9b5cac684 100644 --- a/app/helpers/filter_helper.rb +++ b/app/helpers/filter_helper.rb @@ -81,4 +81,12 @@ module FilterHelper def default_filter(query_hash, filter_operator_value) "#{filter_config[:table_name]}.#{query_hash[:attribute_key]} #{filter_operator_value} #{query_hash[:query_operator]}" end + + def validate_single_condition(condition) + return if condition['query_operator'].nil? + return if condition['query_operator'].empty? + + operator = condition['query_operator'].upcase + raise CustomExceptions::CustomFilter::InvalidQueryOperator.new({}) unless %w[AND OR].include?(operator) + end end diff --git a/app/javascript/dashboard/api/contacts.js b/app/javascript/dashboard/api/contacts.js index 85c4bba1d..2eee3f484 100644 --- a/app/javascript/dashboard/api/contacts.js +++ b/app/javascript/dashboard/api/contacts.js @@ -27,6 +27,14 @@ class ContactAPI extends ApiClient { return axios.get(requestURL); } + show(id) { + return axios.get(`${this.url}/${id}?include_contact_inboxes=false`); + } + + update(id, data) { + return axios.patch(`${this.url}/${id}?include_contact_inboxes=false`, data); + } + getConversations(contactId) { return axios.get(`${this.url}/${contactId}/conversations`); } diff --git a/app/javascript/dashboard/api/integrations.js b/app/javascript/dashboard/api/integrations.js index 59a3e244a..b78a2ea7e 100644 --- a/app/javascript/dashboard/api/integrations.js +++ b/app/javascript/dashboard/api/integrations.js @@ -36,6 +36,10 @@ class IntegrationsAPI extends ApiClient { requestCaptain(body) { return axios.post(`${this.baseUrl()}/integrations/captain/proxy`, body); } + + requestCaptainCopilot(body) { + return axios.post(`${this.baseUrl()}/integrations/captain/copilot`, body); + } } export default new IntegrationsAPI(); diff --git a/app/javascript/dashboard/assets/scss/_date-picker.scss b/app/javascript/dashboard/assets/scss/_date-picker.scss index 92deab095..2fa577673 100644 --- a/app/javascript/dashboard/assets/scss/_date-picker.scss +++ b/app/javascript/dashboard/assets/scss/_date-picker.scss @@ -25,7 +25,7 @@ } .mx-input { - @apply h-[2.5rem] flex border border-solid border-slate-200 dark:border-slate-600 rounded-md shadow-none; + @apply h-[2.5rem] flex border border-solid border-n-weak rounded-md shadow-none; } .mx-input:disabled, @@ -39,7 +39,7 @@ } .mx-datepicker-main { - @apply border-0 bg-white dark:bg-slate-800; + @apply border-0 bg-n-solid-2 rounded-xl; .cell { &.disabled { @@ -53,6 +53,14 @@ } } + .mx-calendar+.mx-calendar { + @apply border-l border-n-weak; + } + + .mx-datepicker-footer { + @apply border border-n-weak; + } + .mx-time { @apply border-0 bg-white dark:bg-slate-800; diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss index e3474e616..c6304cf19 100644 --- a/app/javascript/dashboard/assets/scss/_woot.scss +++ b/app/javascript/dashboard/assets/scss/_woot.scss @@ -72,6 +72,19 @@ --slate-11: 96 100 108; --slate-12: 28 32 36; + --iris-1: 253 253 255; + --iris-2: 248 248 255; + --iris-3: 240 241 254; + --iris-4: 230 231 255; + --iris-5: 218 220 255; + --iris-6: 203 205 255; + --iris-7: 184 186 248; + --iris-8: 155 158 240; + --iris-9: 91 91 214; + --iris-10: 81 81 205; + --iris-11: 87 83 198; + --iris-12: 39 41 98; + --ruby-1: 255 252 253; --ruby-2: 255 247 248; --ruby-3: 254 234 237; @@ -122,6 +135,7 @@ --solid-active: 255 255 255; --solid-amber: 252 232 193; --solid-blue: 218 236 255; + --solid-iris: 230 231 255; --alpha-1: 67, 67, 67, 0.06; --alpha-2: 201, 202, 207, 0.15; @@ -129,10 +143,10 @@ --black-alpha-1: 0, 0, 0, 0.12; --black-alpha-2: 0, 0, 0, 0.04; --border-blue: 39, 129, 246, 0.5; - --white-alpha: 255, 255, 255, 0.1; + --white-alpha: 255, 255, 255, 0.8; } - body.dark { + .dark { /* slate */ --slate-1: 17 17 19; --slate-2: 24 25 27; @@ -147,6 +161,19 @@ --slate-11: 176 180 186; --slate-12: 237 238 240; + --iris-1: 19 19 30; + --iris-2: 23 22 37; + --iris-3: 32 34 72; + --iris-4: 38 42 101; + --iris-5: 48 51 116; + --iris-6: 61 62 130; + --iris-7: 74 74 149; + --iris-8: 89 88 177; + --iris-9: 91 91 214; + --iris-10: 84 114 228; + --iris-11: 158 177 255; + --iris-12: 224 223 254; + --ruby-1: 25 17 19; --ruby-2: 30 21 23; --ruby-3: 58 20 30; @@ -195,6 +222,7 @@ --solid-active: 53 57 66; --solid-amber: 42 37 30; --solid-blue: 16 49 91; + --solid-iris: 38 42 101; --text-blue: 126 182 255; --alpha-1: 36, 36, 36, 0.8; @@ -204,7 +232,7 @@ --black-alpha-2: 0, 0, 0, 0.2; --border-blue: 39, 129, 246, 0.5; --border-container: 236, 236, 236, 0; - --white-alpha: 255, 255, 255, 0.1; + --white-alpha: 255, 255, 255, 0.8; } /* NEXT COLORS END */ diff --git a/app/javascript/dashboard/assets/scss/widgets/_tabs.scss b/app/javascript/dashboard/assets/scss/widgets/_tabs.scss index b9999fac9..01ccaf671 100644 --- a/app/javascript/dashboard/assets/scss/widgets/_tabs.scss +++ b/app/javascript/dashboard/assets/scss/widgets/_tabs.scss @@ -6,6 +6,14 @@ @apply border-b border-slate-50 dark:border-slate-800/50; } +.tabs--container--compact.tab--chat-type { + .tabs-title { + a { + @apply py-2 text-sm; + } + } +} + .tabs { @apply border-r-0 border-l-0 border-t-0 flex min-w-[6.25rem] py-0 px-4 list-none mb-0; } diff --git a/app/javascript/dashboard/components-next/Campaigns/CampaignCard/CampaignCard.vue b/app/javascript/dashboard/components-next/Campaigns/CampaignCard/CampaignCard.vue index dbdbb5b45..229553253 100644 --- a/app/javascript/dashboard/components-next/Campaigns/CampaignCard/CampaignCard.vue +++ b/app/javascript/dashboard/components-next/Campaigns/CampaignCard/CampaignCard.vue @@ -82,60 +82,56 @@ const inboxIcon = computed(() => { diff --git a/app/javascript/dashboard/components-next/Campaigns/CampaignCard/LiveChatCampaignDetails.vue b/app/javascript/dashboard/components-next/Campaigns/CampaignCard/LiveChatCampaignDetails.vue index 6f8c548d4..6a883ce6b 100644 --- a/app/javascript/dashboard/components-next/Campaigns/CampaignCard/LiveChatCampaignDetails.vue +++ b/app/javascript/dashboard/components-next/Campaigns/CampaignCard/LiveChatCampaignDetails.vue @@ -1,7 +1,8 @@ + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue new file mode 100644 index 000000000..a3b0bf37c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue @@ -0,0 +1,183 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/ContactsCard.story.vue b/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/ContactsCard.story.vue new file mode 100644 index 000000000..3f8d5a411 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/ContactsCard.story.vue @@ -0,0 +1,67 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/fixtures.js b/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/fixtures.js new file mode 100644 index 000000000..67bdba9b4 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsCard/story/fixtures.js @@ -0,0 +1,149 @@ +export default [ + { + additionalAttributes: { + socialProfiles: {}, + }, + availabilityStatus: null, + email: 'johndoe@chatwoot.com', + id: 370, + name: 'John Doe', + phoneNumber: '+918634322418', + identifier: null, + thumbnail: 'https://api.dicebear.com/9.x/thumbs/svg?seed=Felix', + customAttributes: {}, + lastActivityAt: 1731608270, + createdAt: 1731586271, + }, + { + additionalAttributes: { + city: 'kerala', + country: 'India', + description: 'Curious about the web. ', + companyName: 'Chatwoot', + countryCode: '', + socialProfiles: { + github: 'abozler', + twitter: 'ozler', + facebook: 'abozler', + linkedin: 'abozler', + instagram: 'ozler', + }, + }, + availabilityStatus: null, + email: 'ozler@chatwoot.com', + id: 29, + name: 'Abraham Ozlers', + phoneNumber: '+246232222222', + identifier: null, + thumbnail: 'https://api.dicebear.com/9.x/thumbs/svg?seed=Upload', + customAttributes: { + dateContact: '2024-02-01T00:00:00.000Z', + linkContact: 'https://staging.chatwoot.com/app/accounts/3/contacts-new', + listContact: 'Not spam', + numberContact: '12', + }, + lastActivityAt: 1712127410, + createdAt: 1712127389, + }, + { + additionalAttributes: { + city: 'Kerala', + country: 'India', + description: + "I'm Candice developer focusing on building things for the web šŸŒ. Currently, I’m working as a Product Developer here at @chatwootapp āš”ļøšŸ”„", + companyName: 'Chatwoot', + countryCode: 'IN', + socialProfiles: { + github: 'cmathersonj', + twitter: 'cmather', + facebook: 'cmathersonj', + linkedin: 'cmathersonj', + instagram: 'cmathersonjs', + }, + }, + availabilityStatus: null, + email: 'cmathersonj@va.test', + id: 22, + name: 'Candice Matherson', + phoneNumber: '+917474774742', + identifier: null, + thumbnail: 'https://api.dicebear.com/9.x/thumbs/svg?seed=Emery', + customAttributes: { + dateContact: '2024-11-12T03:23:06.963Z', + linkContact: 'https://sd.sd', + textContact: 'hey', + numberContact: '12', + checkboxContact: true, + }, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + city: '', + country: '', + description: '', + companyName: '', + countryCode: '', + socialProfiles: { + github: '', + twitter: '', + facebook: '', + linkedin: '', + instagram: '', + }, + }, + availabilityStatus: null, + email: 'ofolkardi@taobao.test', + id: 21, + name: 'Ophelia Folkard', + phoneNumber: '', + identifier: null, + thumbnail: + 'https://sivin-tunnel.chatwoot.dev/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBPZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--08dcac8eb72ef12b2cad92d58dddd04cd8a5f513/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2RTNKbGMybDZaVjkwYjE5bWFXeHNXd2RwQWZvdyIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--df796c2af3c0153e55236c2f3cf3a199ac2cb6f7/32.jpg', + customAttributes: {}, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + socialProfiles: {}, + }, + availabilityStatus: null, + email: 'wcasteloth@exblog.jp', + id: 20, + name: 'Willy Castelot', + phoneNumber: '+919384', + identifier: null, + thumbnail: 'https://api.dicebear.com/9.x/thumbs/svg?seed=Jade', + customAttributes: {}, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + city: '', + country: '', + description: '', + companyName: '', + countryCode: '', + socialProfiles: { + github: '', + twitter: '', + facebook: '', + linkedin: '', + instagram: '', + }, + }, + availabilityStatus: null, + email: 'ederingtong@printfriendly.test', + id: 19, + name: 'Elisabeth Derington', + phoneNumber: '', + identifier: null, + thumbnail: 'https://api.dicebear.com/9.x/avataaars/svg?seed=Jade', + customAttributes: {}, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, +]; diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue b/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue new file mode 100644 index 000000000..ad007af1c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue @@ -0,0 +1,89 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ConfirmContactDeleteDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ConfirmContactDeleteDialog.vue new file mode 100644 index 000000000..d9c0deb1b --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ConfirmContactDeleteDialog.vue @@ -0,0 +1,58 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactExportDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactExportDialog.vue new file mode 100644 index 000000000..d2b57cbb8 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactExportDialog.vue @@ -0,0 +1,66 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactImportDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactImportDialog.vue new file mode 100644 index 000000000..acb8f0f1c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactImportDialog.vue @@ -0,0 +1,134 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactMergeForm.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactMergeForm.vue new file mode 100644 index 000000000..8adcce6b2 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactMergeForm.vue @@ -0,0 +1,112 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue new file mode 100644 index 000000000..9d172cdf9 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue @@ -0,0 +1,315 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateNewContactDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateNewContactDialog.vue new file mode 100644 index 000000000..806fcf4ac --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateNewContactDialog.vue @@ -0,0 +1,68 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateSegmentDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateSegmentDialog.vue new file mode 100644 index 000000000..a246c742c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/CreateSegmentDialog.vue @@ -0,0 +1,71 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/DeleteSegmentDialog.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/DeleteSegmentDialog.vue new file mode 100644 index 000000000..60aa0e55e --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/DeleteSegmentDialog.vue @@ -0,0 +1,43 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactMergeForm.story.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactMergeForm.story.vue new file mode 100644 index 000000000..dbf22dadd --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactMergeForm.story.vue @@ -0,0 +1,73 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactsForm.story.vue b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactsForm.story.vue new file mode 100644 index 000000000..306df1df0 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/ContactsForm.story.vue @@ -0,0 +1,80 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/fixtures.js b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/fixtures.js new file mode 100644 index 000000000..9d9590d63 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsForm/story/fixtures.js @@ -0,0 +1,47 @@ +export const contactData = { + id: 370, + name: 'John Doe', + email: 'johndoe@chatwoot.com', + phoneNumber: '+918634322418', + additionalAttributes: { + city: 'Kerala', + country: 'India', + description: 'Curious about the web.', + companyName: 'Chatwoot', + countryCode: 'IN', + socialProfiles: { + github: 'johndoe', + twitter: 'johndoe', + facebook: 'johndoe', + linkedin: 'johndoe', + instagram: 'johndoe', + }, + }, +}; + +export const primaryContactList = [ + { + id: 1, + name: 'Jane Smith', + email: 'jane@chatwoot.com', + thumbnail: '', + label: '(ID: 1) Jane Smith', + value: 1, + }, + { + id: 2, + name: 'Mike Johnson', + email: 'mike@chatwoot.com', + thumbnail: '', + label: '(ID: 2) Mike Johnson', + value: 2, + }, + { + id: 3, + name: 'Sarah Wilson', + email: 'sarah@chatwoot.com', + thumbnail: '', + label: '(ID: 3) Sarah Wilson', + value: 3, + }, +]; diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue new file mode 100644 index 000000000..44350bba1 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue @@ -0,0 +1,143 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue new file mode 100644 index 000000000..627addff8 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue @@ -0,0 +1,311 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactMoreActions.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactMoreActions.vue new file mode 100644 index 000000000..d5932535c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactMoreActions.vue @@ -0,0 +1,62 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue new file mode 100644 index 000000000..b263b882d --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue @@ -0,0 +1,138 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactsActiveFiltersPreview.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactsActiveFiltersPreview.vue new file mode 100644 index 000000000..36162520d --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactsActiveFiltersPreview.vue @@ -0,0 +1,69 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/story/ContactHeader.story.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/story/ContactHeader.story.vue new file mode 100644 index 000000000..a89aa724c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/story/ContactHeader.story.vue @@ -0,0 +1,106 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue b/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue new file mode 100644 index 000000000..22b32d7b8 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue @@ -0,0 +1,103 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributeItem.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributeItem.vue new file mode 100644 index 000000000..dc52d8912 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributeItem.vue @@ -0,0 +1,95 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributes.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributes.vue new file mode 100644 index 000000000..f2a5c1ee8 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactCustomAttributes.vue @@ -0,0 +1,129 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactHistory.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactHistory.vue new file mode 100644 index 000000000..3763d198a --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactHistory.vue @@ -0,0 +1,54 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue new file mode 100644 index 000000000..2a0e79931 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue @@ -0,0 +1,145 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactNotes.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactNotes.vue new file mode 100644 index 000000000..dfe3f437c --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactNotes.vue @@ -0,0 +1,99 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/ContactNoteItem.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/ContactNoteItem.vue new file mode 100644 index 000000000..504be1547 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/ContactNoteItem.vue @@ -0,0 +1,63 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/ContactNoteItem.story.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/ContactNoteItem.story.vue new file mode 100644 index 000000000..0dbf8bf01 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/ContactNoteItem.story.vue @@ -0,0 +1,39 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/fixtures.js b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/fixtures.js new file mode 100644 index 000000000..440ad95df --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/components/story/fixtures.js @@ -0,0 +1,69 @@ +export default [ + { + id: 12, + content: + 'This tutorial will show you how to use Chatwoot and, hence, ensure you practice effective customer communication. We will explain in detail the following:\n\n* Step-by-step setup of your account, with illustrative screenshots.\n\n* An in-depth explanation of all the core features of Chatwoot.\n\n* Get your account up and running by the end of this tutorial.\n\n* Basic concepts of customer communication.', + accountId: null, + contactId: null, + user: { + id: 30, + account_id: 2, + availability_status: 'offline', + auto_offline: true, + confirmed: true, + email: 'bruce@paperlayer.test', + available_name: 'Bruce', + name: 'Bruce', + role: 'administrator', + thumbnail: + 'https://sivin-tunnel.chatwoot.dev/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBJZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--515dbb35e9ba3c36d14f4c4b77220a675513c1fb/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJYW5CbkJqb0dSVlE2RTNKbGMybDZaVjkwYjE5bWFXeHNXd2RwQWZvdyIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--df796c2af3c0153e55236c2f3cf3a199ac2cb6f7/2.jpg', + custom_role_id: null, + }, + createdAt: 1730786556, + updatedAt: 1730786556, + }, + { + id: 10, + content: + 'We discussed a couple of things:\n\n* Product offering and how it can be useful to talk with people.\n\n* They’ll reach out to us after an internal review.', + accountId: null, + contactId: null, + user: { + id: 1, + account_id: 2, + availability_status: 'online', + auto_offline: false, + confirmed: true, + email: 'hillary@chatwoot.com', + available_name: 'Hillary', + name: 'Hillary', + role: 'administrator', + thumbnail: '', + custom_role_id: null, + }, + createdAt: 1730782566, + updatedAt: 1730782566, + }, + { + id: 9, + content: + 'We discussed a couple of things:\n\n* Product offering and how it can be useful to talk with people.\n\n* They’ll reach out to us after an internal review.', + accountId: null, + contactId: null, + user: { + id: 1, + account_id: 2, + availability_status: 'online', + auto_offline: false, + confirmed: true, + email: 'john@chatwoot.com', + available_name: 'John', + name: 'John', + role: 'administrator', + thumbnail: '', + custom_role_id: null, + }, + createdAt: 1730782564, + updatedAt: 1730782564, + }, +]; diff --git a/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.story.vue b/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.story.vue new file mode 100644 index 000000000..0c1998a84 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.story.vue @@ -0,0 +1,28 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.vue b/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.vue new file mode 100644 index 000000000..f6f5ddaf6 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/EmptyState/ContactEmptyState.vue @@ -0,0 +1,66 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/EmptyState/contactEmptyStateContent.js b/app/javascript/dashboard/components-next/Contacts/EmptyState/contactEmptyStateContent.js new file mode 100644 index 000000000..6d80c9151 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/EmptyState/contactEmptyStateContent.js @@ -0,0 +1,228 @@ +export default [ + { + additionalAttributes: { + city: 'Los Angeles', + country: 'United States', + description: + "I'm Candice, a developer focusing on building web solutions. Currently, I’m working as a Product Developer at Chatwoot.", + companyName: 'Chatwoot', + countryCode: 'US', + socialProfiles: { + github: 'candice-dev', + twitter: 'candice_w_dev', + facebook: 'candice.dev', + linkedin: 'candice-matherson', + instagram: 'candice.codes', + }, + }, + availabilityStatus: 'offline', + email: 'candice.matherson@chatwoot.com', + id: 22, + name: 'Candice Matherson', + phoneNumber: '+14155552671', + identifier: null, + thumbnail: '', + customAttributes: { + dateContact: '2024-11-11T11:53:09.299Z', + linkContact: 'https://example.com', + listContact: 'Follow-Up', + textContact: 'Hi there!', + numberContact: '42', + checkboxContact: false, + }, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + city: 'San Francisco', + country: 'United States', + description: 'Passionate about design and user experience.', + companyName: 'Designify', + countryCode: 'US', + socialProfiles: { + github: 'ophelia-folkard', + twitter: 'oph_designs', + facebook: 'ophelia.folkard', + linkedin: 'ophelia-folkard', + instagram: 'ophelia.design', + }, + }, + availabilityStatus: 'offline', + email: 'ophelia.folkard@designify.com', + id: 21, + name: 'Ophelia Folkard', + phoneNumber: '+14155552672', + identifier: null, + thumbnail: '', + customAttributes: { + dateContact: '2024-10-05T10:12:34.567Z', + linkContact: 'https://designify.com', + listContact: 'Prospects', + textContact: 'Looking forward to connecting!', + }, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + city: 'Austin', + country: 'United States', + description: 'Avid coder and tech enthusiast.', + companyName: 'CodeHub', + countryCode: 'US', + socialProfiles: { + github: 'willy_castelot', + twitter: 'willy_code', + facebook: 'willy.castelot', + linkedin: 'willy-castelot', + instagram: 'willy.coder', + }, + }, + availabilityStatus: 'offline', + email: 'willy.castelot@codehub.io', + id: 20, + name: 'Willy Castelot', + phoneNumber: '+14155552673', + identifier: null, + thumbnail: '', + customAttributes: { + textContact: 'Let’s collaborate!', + checkboxContact: true, + }, + lastActivityAt: 1712123233, + createdAt: 1712123233, + }, + { + additionalAttributes: { + city: 'Seattle', + country: 'United States', + description: 'Product manager with a love for innovation.', + companyName: 'InnovaTech', + countryCode: 'US', + socialProfiles: { + github: 'elisabeth-d', + twitter: 'elisabeth_innova', + facebook: 'elisabeth.derington', + linkedin: 'elisabeth-derington', + instagram: 'elisabeth.innovates', + }, + }, + availabilityStatus: 'offline', + email: 'elisabeth.derington@innova.com', + id: 19, + name: 'Elisabeth Derington', + phoneNumber: '+14155552674', + identifier: null, + thumbnail: '', + customAttributes: { + textContact: 'Let’s schedule a call.', + }, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, + { + additionalAttributes: { + city: 'Chicago', + country: 'United States', + description: 'Marketing specialist and content creator.', + companyName: 'Contently', + countryCode: 'US', + socialProfiles: { + github: 'olia-olenchenko', + twitter: 'olia_content', + facebook: 'olia.olenchenko', + linkedin: 'olia-olenchenko', + instagram: 'olia.creates', + }, + }, + availabilityStatus: 'offline', + email: 'olia.olenchenko@contently.com', + id: 18, + name: 'Olia Olenchenko', + phoneNumber: '+14155552675', + identifier: null, + thumbnail: '', + customAttributes: {}, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, + { + additionalAttributes: { + city: 'Boston', + country: 'United States', + description: 'SEO expert and analytics enthusiast.', + companyName: 'OptiSearch', + countryCode: 'US', + socialProfiles: { + github: 'nate-vannuchi', + twitter: 'nate_seo', + facebook: 'nathaniel.vannuchi', + linkedin: 'nathaniel-vannuchi', + instagram: 'nate.optimizes', + }, + }, + availabilityStatus: 'offline', + email: 'nathaniel.vannuchi@optisearch.com', + id: 17, + name: 'Nathaniel Vannuchi', + phoneNumber: '+14155552676', + identifier: null, + thumbnail: '', + customAttributes: {}, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, + { + additionalAttributes: { + city: 'Denver', + country: 'United States', + description: 'UI/UX designer with a flair for minimalist designs.', + companyName: 'Minimal Designs', + countryCode: 'US', + socialProfiles: { + github: 'merrile-petruk', + twitter: 'merrile_ux', + facebook: 'merrile.petruk', + linkedin: 'merrile-petruk', + instagram: 'merrile.designs', + }, + }, + availabilityStatus: 'offline', + email: 'merrile.petruk@minimal.com', + id: 16, + name: 'Merrile Petruk', + phoneNumber: '+14155552677', + identifier: null, + thumbnail: '', + customAttributes: {}, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, + { + additionalAttributes: { + city: 'Miami', + country: 'United States', + description: 'Entrepreneur with a background in e-commerce.', + companyName: 'Ecom Solutions', + countryCode: 'US', + socialProfiles: { + github: 'cordell-d', + twitter: 'cordell_entrepreneur', + facebook: 'cordell.dalinder', + linkedin: 'cordell-dalinder', + instagram: 'cordell.ecom', + }, + }, + availabilityStatus: 'offline', + email: 'cordell.dalinder@ecomsolutions.com', + id: 15, + name: 'Cordell Dalinder', + phoneNumber: '+14155552678', + identifier: null, + thumbnail: '', + customAttributes: {}, + lastActivityAt: 1712123232, + createdAt: 1712123232, + }, +]; diff --git a/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue b/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue new file mode 100644 index 000000000..aec21a976 --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue @@ -0,0 +1,200 @@ + + + diff --git a/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue b/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue new file mode 100644 index 000000000..33532edcf --- /dev/null +++ b/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue @@ -0,0 +1,81 @@ + + + diff --git a/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardMessagePreview.vue b/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardMessagePreview.vue index dfa31e100..a81c80b87 100644 --- a/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardMessagePreview.vue +++ b/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardMessagePreview.vue @@ -1,6 +1,7 @@