Merge branch 'release/1.16.0'

This commit is contained in:
Sojan 2021-05-18 00:08:00 +05:30
commit 10f3d321de
557 changed files with 19291 additions and 4575 deletions

View file

@ -30,3 +30,6 @@ exclude_patterns:
- "**/*.md"
- "**/*.yml"
- "app/javascript/dashboard/i18n/locale"
- "stories/**/*"
- "**/*.stories.js"
- "**/stories/"

View file

@ -1,5 +1,6 @@
{
"printWidth": 80,
"singleQuote": true,
"trailingComma": "es5"
"trailingComma": "es5",
"arrowParens": "avoid"
}

View file

@ -101,6 +101,7 @@ Rails/BulkChangeTable:
- 'db/migrate/20170511134418_latlong.rb'
- 'db/migrate/20191027054756_create_contact_inboxes.rb'
- 'db/migrate/20191130164019_add_template_type_to_messages.rb'
- 'db/migrate/20210425093724_convert_integration_hook_settings_field.rb'
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/channel/twitter_profile.rb'

44
.storybook/main.js Normal file
View file

@ -0,0 +1,44 @@
const path = require('path');
const resolve = require('../config/webpack/resolve');
// Chatwoot's webpack.config.js
process.env.NODE_ENV = 'development';
const custom = require('../config/webpack/environment');
module.exports = {
stories: [
'../stories/**/*.stories.mdx',
'../app/javascript/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [
{
name: '@storybook/addon-docs',
options: {
vueDocgenOptions: {
alias: {
'@': path.resolve(__dirname, '../'),
},
},
},
},
'@storybook/addon-links',
'@storybook/addon-essentials',
],
webpackFinal: config => {
const newConfig = {
...config,
resolve: {
...config.resolve,
modules: custom.resolvedModules.map(i => i.value),
},
};
newConfig.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../app/javascript'),
});
return newConfig;
},
};

38
.storybook/preview.js Normal file
View file

@ -0,0 +1,38 @@
import { addDecorator } from '@storybook/vue';
import Vue from 'vue';
import Vuex from 'vuex';
import VueI18n from 'vue-i18n';
import WootUiKit from '../app/javascript/dashboard/components';
import i18n from '../app/javascript/dashboard/i18n';
import '../app/javascript/dashboard/assets/scss/storybook.scss';
Vue.use(VueI18n);
Vue.use(WootUiKit);
Vue.use(Vuex);
const store = new Vuex.Store({});
const i18nConfig = new VueI18n({
locale: 'en',
messages: i18n,
});
addDecorator(() => ({
template: '<story/>',
i18n: i18nConfig,
store,
beforeCreate: function() {
this.$root._i18n = this.$i18n;
},
}));
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};

View file

@ -31,6 +31,8 @@ gem 'haikunator'
gem 'liquid'
# Parse Markdown to HTML
gem 'commonmarker'
# Validate Data against JSON Schema
gem 'json_schemer'
##-- for active storage --##
gem 'aws-sdk-s3', require: false
@ -80,6 +82,8 @@ gem 'twitty'
gem 'koala'
# slack client
gem 'slack-ruby-client'
# for dialogflow integrations
gem 'google-cloud-dialogflow'
##--- gems for debugging and error reporting ---##
# static analysis
@ -105,6 +109,8 @@ gem 'maxminddb'
# to create db triggers
gem 'hairtrigger'
gem 'procore-sift'
group :development do
gem 'annotate'
gem 'bullet'
@ -112,7 +118,7 @@ group :development do
gem 'web-console'
# used in swagger build
gem 'json_refs', git: 'https://github.com/tzmfreedom/json_refs', ref: 'e32deb0'
gem 'json_refs', git: 'https://github.com/tzmfreedom/json_refs', ref: '131b11294fd6af9c428171f38516e6222a58c874'
# When we want to squash migrations
gem 'squasher'

View file

@ -7,10 +7,10 @@ GIT
GIT
remote: https://github.com/tzmfreedom/json_refs
revision: e32deb073ce9aef39bdd63556bffd7fe7c2a803d
ref: e32deb0
revision: 131b11294fd6af9c428171f38516e6222a58c874
ref: 131b11294fd6af9c428171f38516e6222a58c874
specs:
json_refs (0.1.2)
json_refs (0.1.6)
hana
GEM
@ -18,58 +18,58 @@ GEM
specs:
action-cable-testing (0.6.1)
actioncable (>= 5.0)
actioncable (6.0.3.6)
actionpack (= 6.0.3.6)
actioncable (6.0.3.7)
actionpack (= 6.0.3.7)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.3.6)
actionpack (= 6.0.3.6)
activejob (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
actionmailbox (6.0.3.7)
actionpack (= 6.0.3.7)
activejob (= 6.0.3.7)
activerecord (= 6.0.3.7)
activestorage (= 6.0.3.7)
activesupport (= 6.0.3.7)
mail (>= 2.7.1)
actionmailer (6.0.3.6)
actionpack (= 6.0.3.6)
actionview (= 6.0.3.6)
activejob (= 6.0.3.6)
actionmailer (6.0.3.7)
actionpack (= 6.0.3.7)
actionview (= 6.0.3.7)
activejob (= 6.0.3.7)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.3.6)
actionview (= 6.0.3.6)
activesupport (= 6.0.3.6)
actionpack (6.0.3.7)
actionview (= 6.0.3.7)
activesupport (= 6.0.3.7)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.3.6)
actionpack (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
actiontext (6.0.3.7)
actionpack (= 6.0.3.7)
activerecord (= 6.0.3.7)
activestorage (= 6.0.3.7)
activesupport (= 6.0.3.7)
nokogiri (>= 1.8.5)
actionview (6.0.3.6)
activesupport (= 6.0.3.6)
actionview (6.0.3.7)
activesupport (= 6.0.3.7)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.3.6)
activesupport (= 6.0.3.6)
activejob (6.0.3.7)
activesupport (= 6.0.3.7)
globalid (>= 0.3.6)
activemodel (6.0.3.6)
activesupport (= 6.0.3.6)
activerecord (6.0.3.6)
activemodel (= 6.0.3.6)
activesupport (= 6.0.3.6)
activemodel (6.0.3.7)
activesupport (= 6.0.3.7)
activerecord (6.0.3.7)
activemodel (= 6.0.3.7)
activesupport (= 6.0.3.7)
activerecord-import (1.0.7)
activerecord (>= 3.2)
activestorage (6.0.3.6)
actionpack (= 6.0.3.6)
activejob (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (6.0.3.7)
actionpack (= 6.0.3.7)
activejob (= 6.0.3.7)
activerecord (= 6.0.3.7)
marcel (~> 1.0.0)
activesupport (6.0.3.6)
activesupport (6.0.3.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@ -79,11 +79,10 @@ GEM
activerecord (>= 5.0, < 6.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
administrate (0.14.0)
actionpack (>= 4.2)
actionview (>= 4.2)
activerecord (>= 4.2)
autoprefixer-rails (>= 6.0)
administrate (0.16.0)
actionpack (>= 5.0)
actionview (>= 5.0)
activerecord (>= 5.0)
datetime_picker_rails (~> 0.0.7)
jquery-rails (>= 4.0)
kaminari (>= 1.0)
@ -95,8 +94,6 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.1)
attr_extras (6.2.4)
autoprefixer-rails (9.8.6.3)
execjs
aws-eventstream (1.1.0)
aws-partitions (1.360.0)
aws-sdk-core (3.105.0)
@ -184,6 +181,8 @@ GEM
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
ecma-re-validator (0.2.1)
regexp_parser (~> 1.2)
equalizer (0.0.11)
erubi (1.10.0)
et-orbi (1.2.4)
@ -205,12 +204,18 @@ GEM
faraday (~> 1.0)
fcm (1.0.2)
faraday (~> 1.0.0)
ffi (1.14.2)
ffi (1.15.0)
flag_shih_tzu (0.3.23)
foreman (0.87.2)
fugit (1.4.1)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.4)
gapic-common (0.3.4)
google-protobuf (~> 3.12, >= 3.12.2)
googleapis-common-protos (>= 1.3.9, < 2.0)
googleapis-common-protos-types (>= 1.0.4, < 2.0)
googleauth (~> 0.9)
grpc (~> 1.25)
geocoder (1.6.3)
gli (2.19.2)
globalid (0.4.2)
@ -223,12 +228,18 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-cloud-core (1.5.0)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.3.3)
google-cloud-dialogflow (1.2.0)
google-cloud-core (~> 1.5)
google-cloud-dialogflow-v2 (~> 0.1)
google-cloud-dialogflow-v2 (0.6.4)
gapic-common (~> 0.3)
google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-errors (1.1.0)
google-cloud-storage (1.28.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
@ -236,7 +247,14 @@ GEM
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.13.1)
google-protobuf (3.15.8)
googleapis-common-protos (1.3.11)
google-protobuf (~> 3.14)
googleapis-common-protos-types (>= 1.0.6, < 2.0)
grpc (~> 1.27)
googleapis-common-protos-types (1.0.6)
google-protobuf (~> 3.14)
googleauth (0.16.2)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
@ -245,12 +263,15 @@ GEM
signet (~> 0.14)
groupdate (5.1.0)
activesupport (>= 5)
grpc (1.37.1)
google-protobuf (~> 3.15)
googleapis-common-protos-types (~> 1.0)
haikunator (1.1.0)
hairtrigger (0.2.23)
activerecord (>= 5.0, < 7)
ruby2ruby (~> 2.4)
ruby_parser (~> 3.10)
hana (1.3.6)
hana (1.3.7)
hashdiff (1.0.1)
hashie (4.1.0)
hkdf (0.3.0)
@ -261,7 +282,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
i18n (1.8.9)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
inflecto (0.0.2)
@ -273,7 +294,12 @@ GEM
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.3.1)
jwt (2.2.2)
json_schemer (0.2.16)
ecma-re-validator (~> 0.2)
hana (~> 1.3)
regexp_parser (~> 1.5)
uri_template (~> 0.7)
jwt (2.2.3)
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
@ -298,12 +324,12 @@ GEM
listen (3.3.3)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.9.0)
loofah (2.9.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (1.0.0)
marcel (1.0.1)
maxminddb (0.1.22)
memoist (0.16.2)
method_source (1.0.0)
@ -311,8 +337,8 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512)
mini_magick (4.10.1)
mini_mime (1.0.3)
mini_portile2 (2.5.0)
mini_mime (1.1.0)
mini_portile2 (2.5.1)
minitest (5.14.4)
momentjs-rails (2.20.1)
railties (>= 3.1)
@ -324,22 +350,24 @@ GEM
connection_pool (~> 2.2)
netrc (0.11.0)
nio4r (2.5.7)
nokogiri (1.11.2)
nokogiri (1.11.3)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
oauth (0.5.4)
oauth (0.5.6)
orm_adapter (0.5.0)
os (1.1.1)
parallel (1.19.2)
parser (2.7.1.4)
ast (~> 2.4.1)
pg (1.2.3)
procore-sift (0.15.0)
rails (> 4.2.0)
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.5)
public_suffix (4.0.6)
puma (4.3.6)
nio4r (~> 2.0)
pundit (2.1.0)
@ -355,29 +383,29 @@ GEM
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.3.6)
actioncable (= 6.0.3.6)
actionmailbox (= 6.0.3.6)
actionmailer (= 6.0.3.6)
actionpack (= 6.0.3.6)
actiontext (= 6.0.3.6)
actionview (= 6.0.3.6)
activejob (= 6.0.3.6)
activemodel (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
rails (6.0.3.7)
actioncable (= 6.0.3.7)
actionmailbox (= 6.0.3.7)
actionmailer (= 6.0.3.7)
actionpack (= 6.0.3.7)
actiontext (= 6.0.3.7)
actionview (= 6.0.3.7)
activejob (= 6.0.3.7)
activemodel (= 6.0.3.7)
activerecord (= 6.0.3.7)
activestorage (= 6.0.3.7)
activesupport (= 6.0.3.7)
bundler (>= 1.3.0)
railties (= 6.0.3.6)
railties (= 6.0.3.7)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.3.6)
actionpack (= 6.0.3.6)
activesupport (= 6.0.3.6)
railties (6.0.3.7)
actionpack (= 6.0.3.7)
activesupport (= 6.0.3.7)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
@ -408,7 +436,7 @@ GEM
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
retriable (3.1.2)
rexml (3.2.4)
rexml (3.2.5)
rspec-core (3.9.2)
rspec-support (~> 3.9.3)
rspec-expectations (3.9.2)
@ -489,7 +517,7 @@ GEM
sidekiq-cron (1.2.0)
fugit (~> 1.1)
sidekiq (>= 4.2.1)
signet (0.14.0)
signet (0.15.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
@ -547,6 +575,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
uniform_notifier (1.13.0)
uri_template (0.7.0)
valid_email2 (3.3.1)
activemodel (>= 3.2)
mail (~> 2.5)
@ -612,6 +641,7 @@ DEPENDENCIES
flag_shih_tzu
foreman
geocoder
google-cloud-dialogflow
google-cloud-storage
groupdate
haikunator
@ -619,6 +649,7 @@ DEPENDENCIES
hashie
jbuilder
json_refs!
json_schemer
jwt
kaminari
koala
@ -629,6 +660,7 @@ DEPENDENCIES
mini_magick
mock_redis!
pg
procore-sift
pry-rails
puma
pundit

View file

@ -0,0 +1,38 @@
class Campaigns::CampaignConversationBuilder
pattr_initialize [:contact_inbox_id!, :campaign_display_id!, :conversation_additional_attributes]
def perform
@contact_inbox = ContactInbox.find(@contact_inbox_id)
@campaign = @contact_inbox.inbox.campaigns.find_by!(display_id: campaign_display_id)
ActiveRecord::Base.transaction do
@contact_inbox.lock!
# We won't send campaigns if a conversation is already present
return if @contact_inbox.reload.conversations.present?
@conversation = ::Conversation.create!(conversation_params)
Messages::MessageBuilder.new(@campaign.sender, @conversation, message_params).perform
end
@conversation
end
private
def message_params
ActionController::Parameters.new({
content: @campaign.message
})
end
def conversation_params
{
account_id: @campaign.account_id,
inbox_id: @contact_inbox.inbox_id,
contact_id: @contact_inbox.contact_id,
contact_inbox_id: @contact_inbox.id,
campaign_id: @campaign.id,
additional_attributes: conversation_additional_attributes
}
end
end

View file

@ -0,0 +1,28 @@
class Api::V1::Accounts::CampaignsController < Api::V1::Accounts::BaseController
before_action :campaign, except: [:index, :create]
before_action :check_authorization
def index
@campaigns = Current.account.campaigns
end
def create
@campaign = Current.account.campaigns.create!(campaign_params)
end
def show; end
def update
@campaign.update(campaign_params)
end
private
def campaign
@campaign ||= Current.account.campaigns.find_by(display_id: params[:id])
end
def campaign_params
params.require(:campaign).permit(:title, :description, :message, :enabled, :inbox_id, :sender_id, trigger_rules: {})
end
end

View file

@ -1,4 +1,11 @@
class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
include Sift
sort_on :email, type: :string
sort_on :name, type: :string
sort_on :phone_number, type: :string
sort_on :last_activity_at, type: :datetime
RESULTS_PER_PAGE = 15
protect_from_forgery with: :null_session
@ -68,7 +75,6 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
@resolved_contacts ||= Current.account.contacts
.where.not(email: [nil, ''])
.or(Current.account.contacts.where.not(phone_number: [nil, '']))
.order('LOWER(name)')
end
def set_current_page
@ -76,11 +82,11 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
end
def fetch_contact_last_seen_at(contacts)
contacts.left_outer_joins(:conversations)
.select('contacts.*, COUNT(conversations.id) as conversations_count, MAX(conversations.contact_last_seen_at) as last_seen_at')
.group('contacts.id')
.includes([{ avatar_attachment: [:blob] }, { contact_inboxes: [:inbox] }])
.page(@current_page).per(RESULTS_PER_PAGE)
filtrate(contacts).left_outer_joins(:conversations)
.select('contacts.*, COUNT(conversations.id) as conversations_count')
.group('contacts.id')
.includes([{ avatar_attachment: [:blob] }, { contact_inboxes: [:inbox] }])
.page(@current_page).per(RESULTS_PER_PAGE)
end
def build_contact_inbox

View file

@ -11,6 +11,10 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
@assignable_agents = (Current.account.users.where(id: @inbox.members.select(:user_id)) + Current.account.administrators).uniq
end
def campaigns
@campaigns = @inbox.campaigns
end
def create
ActiveRecord::Base.transaction do
channel = create_channel

View file

@ -0,0 +1,31 @@
class Api::V1::Accounts::Integrations::HooksController < Api::V1::Accounts::BaseController
before_action :fetch_hook, only: [:update, :destroy]
before_action :check_authorization
def create
@hook = Current.account.hooks.create!(permitted_params)
end
def update
@hook.update!(permitted_params.slice(:status, :settings))
end
def destroy
@hook.destroy
head :ok
end
private
def fetch_hook
@hook = Current.account.hooks.find(params[:id])
end
def check_authorization
authorize(:hook)
end
def permitted_params
params.require(:hook).permit(:app_id, :inbox_id, :status, settings: {})
end
end

View file

@ -0,0 +1,13 @@
class Api::V1::Widget::CampaignsController < Api::V1::Widget::BaseController
skip_before_action :set_contact
def index
@campaigns = @web_widget.inbox.campaigns.where(enabled: true)
end
private
def permitted_params
params.permit(:website_token)
end
end

View file

@ -2,7 +2,8 @@ class Api::V1::Widget::EventsController < Api::V1::Widget::BaseController
include Events::Types
def create
Rails.configuration.dispatcher.dispatch(permitted_params[:name], Time.zone.now, contact_inbox: @contact_inbox, event_info: event_info)
Rails.configuration.dispatcher.dispatch(permitted_params[:name], Time.zone.now, contact_inbox: @contact_inbox,
event_info: permitted_params[:event_info].to_h.merge(event_info))
head :no_content
end
@ -17,6 +18,6 @@ class Api::V1::Widget::EventsController < Api::V1::Widget::BaseController
end
def permitted_params
params.permit(:name, :website_token)
params.permit(:name, :website_token, event_info: {})
end
end

View file

@ -12,7 +12,8 @@ class AsyncDispatcher < BaseDispatcher
[
EventListener.instance,
WebhookListener.instance,
InstallationWebhookListener.instance, HookListener.instance
InstallationWebhookListener.instance, HookListener.instance,
CampaignListener.instance
]
end
end

View file

@ -0,0 +1,9 @@
import ApiClient from './ApiClient';
class CampaignsAPI extends ApiClient {
constructor() {
super('campaigns', { accountScoped: true });
}
}
export default new CampaignsAPI();

View file

@ -6,8 +6,8 @@ class ContactAPI extends ApiClient {
super('contacts', { accountScoped: true });
}
get(page) {
return axios.get(`${this.url}?page=${page}`);
get(page, sortAttr = 'name') {
return axios.get(`${this.url}?page=${page}&sort=${sortAttr}`);
}
getConversations(contactId) {
@ -18,8 +18,10 @@ class ContactAPI extends ApiClient {
return axios.get(`${this.url}/${contactId}/contactable_inboxes`);
}
search(search = '', page = 1) {
return axios.get(`${this.url}/search?q=${search}&page=${page}`);
search(search = '', page = 1, sortAttr = 'name') {
return axios.get(
`${this.url}/search?q=${search}&page=${page}&sort=${sortAttr}`
);
}
}

View file

@ -1,9 +1,18 @@
/* global axios */
import ApiClient from './ApiClient';
class Inboxes extends ApiClient {
constructor() {
super('inboxes', { accountScoped: true });
}
getAssignableAgents(inboxId) {
return axios.get(`${this.url}/${inboxId}/assignable_agents`);
}
getCampaigns(inboxId) {
return axios.get(`${this.url}/${inboxId}/campaigns`);
}
}
export default new Inboxes();

View file

@ -0,0 +1,13 @@
import campaigns from '../campaigns';
import ApiClient from '../ApiClient';
describe('#CampaignAPI', () => {
it('creates correct instance', () => {
expect(campaigns).toBeInstanceOf(ApiClient);
expect(campaigns).toHaveProperty('get');
expect(campaigns).toHaveProperty('show');
expect(campaigns).toHaveProperty('create');
expect(campaigns).toHaveProperty('update');
expect(campaigns).toHaveProperty('delete');
});
});

View file

@ -15,10 +15,6 @@
}
}
.label {
font-weight: $font-weight-bold;
}
.tooltip {
border-radius: $space-smaller;
font-size: $font-size-mini;

View file

@ -358,7 +358,7 @@ $form-label-font-weight: $font-weight-medium;
$form-label-line-height: 1.8;
$select-background: $white;
$select-triangle-color: $dark-gray;
$select-radius: $global-radius;
$select-radius: var(--border-radius-normal);
$input-color: $header-color;
$input-placeholder-color: $light-gray;
$input-font-family: inherit;
@ -374,19 +374,19 @@ $input-shadow-focus: 0;
$input-cursor-disabled: not-allowed;
$input-transition: border-color 0.25s ease-in-out;
$input-number-spinners: true;
$input-radius: $global-radius;
$form-button-radius: $global-radius;
$input-radius: var(--border-radius-normal);
$form-button-radius: var(--border-radius-normal);
// 20. Label
// ---------
$label-background: lighten($primary-color, 40%);
$label-color: $primary-color;
$label-background: $primary-color;
$label-color: $white;
$label-color-alt: $black;
$label-palette: $foundation-palette;
$label-font-size: $font-size-micro;
$label-font-size: $font-size-mini;
$label-padding: $space-smaller $space-small;
$label-radius: $space-micro;
$label-radius: var(--border-radius-small);
// 21. Media Object
// ----------------

View file

@ -51,25 +51,6 @@
}
}
input,
textarea,
select {
border-radius: var(--space-smaller) !important;
}
.input-group {
.input-group-label:first-child {
border-bottom-left-radius: var(--space-smaller);
border-top-left-radius: var(--space-smaller);
}
.input-group-field {
border-bottom-left-radius: 0 !important;
border-top-left-radius: 0 !important;
}
}
.justify-space-between {
justify-content: space-between;
}

View file

@ -236,3 +236,11 @@ $spinner-before-border-color: rgba(255, 255, 255, 0.7);
text-overflow: ellipsis;
white-space: nowrap;
}
@mixin three-column-grid($column-one-width: 25.6rem,
$column-three-width: 25.6rem) {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: minmax($column-one-width, 6fr) 10fr minmax($column-three-width, 6fr);
}

View file

@ -0,0 +1,27 @@
@import 'shared/assets/fonts/inter';
@import 'shared/assets/stylesheets/colors';
@import 'shared/assets/stylesheets/spacing';
@import 'shared/assets/stylesheets/font-size';
@import 'shared/assets/stylesheets/font-weights';
@import 'shared/assets/stylesheets/shadows';
@import 'shared/assets/stylesheets/border-radius';
@import 'variables';
@import '~spinkit/scss/spinners/7-three-bounce';
@import '~shared/assets/stylesheets/ionicons';
@import 'mixins';
@import 'foundation-settings';
@import 'helper-classes';
@import 'foundation-sites/scss/foundation';
@import '~bourbon/core/bourbon';
@include foundation-everything($flex: true);
@import 'typography';
@import 'layout';
@import 'animations';
@import 'foundation-custom';
@import 'widgets/buttons';
@import 'widgets/forms';

View file

@ -39,20 +39,25 @@ $resolve-button-width: 13.2rem;
.user {
@include flex;
@include flex-align($x: center, $y: middle);
margin-right: var(--space-normal);
min-width: 0;
.user--name {
@include margin(0);
display: inline-block;
font-size: $font-size-medium;
line-height: 1.3;
text-transform: capitalize;
width: 100%;
}
.user--profile__meta {
align-items: flex-start;
display: flex;
flex-direction: column;
justify-content: center;
justify-content: flex-start;
margin-left: $space-slab;
min-width: 0;
}
.user--profile__button {

View file

@ -132,7 +132,6 @@
.bubble {
@include bubble-with-types;
max-width: 50rem;
text-align: left;
word-wrap: break-word;
@ -236,7 +235,9 @@
.wrap {
@include margin($zero $space-normal);
max-width: 69%;
--bubble-max-width: 49.6rem;
max-width: Min(var(--bubble-max-width), 85%);
.sender--name {
font-size: $font-size-mini;

View file

@ -1,7 +1,8 @@
.error {
#{$all-text-inputs},
select,
.multiselect > .multiselect__tags {
.multiselect>.multiselect__tags {
@include thin-border(var(--r-400));
}
@ -33,3 +34,10 @@ input {
.help-text {
font-weight: $font-weight-normal;
}
.input-group.small {
input {
font-size: var(--font-size-small);
height: var(--space-large);
}
}

View file

@ -116,7 +116,7 @@ export default {
return this.$store.getters['inboxes/getInbox'](this.activeInbox);
},
currentPage() {
return this.$store.getters['conversationPage/getCurrentPage'](
return this.$store.getters['conversationPage/getCurrentPageFilter'](
this.activeAssigneeTab
);
},
@ -199,6 +199,7 @@ export default {
},
updateAssigneeTab(selectedTab) {
if (this.activeAssigneeTab !== selectedTab) {
bus.$emit('clearSearchInput');
this.activeAssigneeTab = selectedTab;
if (!this.currentPage) {
this.fetchConversations();

View file

@ -6,8 +6,10 @@ import Button from './ui/WootButton';
import Code from './Code';
import ColorPicker from './widgets/ColorPicker';
import DeleteModal from './widgets/modal/DeleteModal.vue';
import DropdownItem from 'shared/components/ui/dropdown/DropdownItem';
import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu';
import Input from './widgets/forms/Input.vue';
import Label from './widgets/Label.vue';
import Label from './ui/Label';
import LoadingState from './widgets/LoadingState';
import Modal from './Modal';
import ModalHeader from './ModalHeader';
@ -26,6 +28,8 @@ const WootUIKit = {
Code,
ColorPicker,
DeleteModal,
DropdownItem,
DropdownMenu,
Input,
LoadingState,
Label,

View file

@ -1,10 +1,7 @@
<template>
<div class="status">
<div class="status-view">
<div
:class="`status-badge status-badge__${currentUserAvailabilityStatus}`"
/>
<availability-status-badge :status="currentUserAvailabilityStatus" />
<div class="status-view--title">
{{ availabilityDisplayLabel }}
</div>
@ -23,22 +20,28 @@
:key="status.value"
class="status-items"
>
<button
class="button clear status-change--dropdown-button"
:disabled="status.disabled"
<woot-button
variant="clear"
class-names="status-change--dropdown-button"
:is-disabled="status.disabled"
@click="changeAvailabilityStatus(status.value)"
>
<span :class="`status-badge status-badge__${status.value}`" />
<availability-status-badge :status="status.value" />
{{ status.label }}
</button>
</woot-button>
</woot-dropdown-item>
</woot-dropdown-menu>
</div>
</transition>
<button class="status-change--change-button" @click="openStatusMenu">
<woot-button
variant="clear"
color-scheme="secondary"
class-names="status-change--change-button link"
@click="openStatusMenu"
>
{{ $t('SIDEBAR_ITEMS.CHANGE_AVAILABILITY_STATUS') }}
</button>
</woot-button>
</div>
</div>
</template>
@ -48,6 +51,7 @@ import { mapGetters } from 'vuex';
import { mixin as clickaway } from 'vue-clickaway';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
import AvailabilityStatusBadge from '../widgets/conversation/AvailabilityStatusBadge';
const AVAILABILITY_STATUS_KEYS = ['online', 'busy', 'offline'];
@ -55,6 +59,7 @@ export default {
components: {
WootDropdownMenu,
WootDropdownItem,
AvailabilityStatusBadge,
},
mixins: [clickaway],
@ -147,26 +152,6 @@ export default {
}
}
.status-badge {
width: var(--space-one);
height: var(--space-one);
margin-right: var(--space-micro);
display: inline-block;
border-radius: 50%;
&__online {
background: var(--g-400);
}
&__offline {
background: var(--b-600);
}
&__busy {
background: var(--y-700);
}
}
.status-change {
.dropdown-pane {
top: -132px;
@ -177,15 +162,5 @@ export default {
display: flex;
align-items: baseline;
}
& &--change-button {
color: var(--b-600);
font-size: var(--font-size-small);
cursor: pointer;
outline: none;
&:hover {
color: var(--w-600);
}
}
}
</style>

View file

@ -144,6 +144,7 @@ export default {
cssClass: 'menu-title align-justify',
toState: frontendURL(`accounts/${this.accountId}/settings/inboxes`),
toStateName: 'settings_inbox_list',
newLinkRouteName: 'settings_inbox_new',
children: this.inboxes.map(inbox => ({
id: inbox.id,
label: inbox.name,
@ -158,10 +159,13 @@ export default {
icon: 'ion-pound',
label: 'LABELS',
hasSubMenu: true,
newLink: true,
key: 'label',
cssClass: 'menu-title align-justify',
toState: frontendURL(`accounts/${this.accountId}/settings/labels`),
toStateName: 'labels_list',
showModalForNewItem: true,
modalName: 'AddLabel',
children: this.accountLabels.map(label => ({
id: label.id,
label: label.title,
@ -178,10 +182,12 @@ export default {
icon: 'ion-ios-people',
label: 'TEAMS',
hasSubMenu: true,
newLink: true,
key: 'team',
cssClass: 'menu-title align-justify teams-sidebar-menu',
toState: frontendURL(`accounts/${this.accountId}/settings/teams`),
toStateName: 'teams_list',
newLinkRouteName: 'settings_teams_new',
children: this.teams.map(team => ({
id: team.id,
label: team.name,

View file

@ -19,7 +19,7 @@
<span
v-if="showItem(menuItem)"
class="child-icon ion-android-add-circle"
@click.prevent="newLinkClick"
@click.prevent="newLinkClick(menuItem)"
/>
</a>
<ul v-if="menuItem.hasSubMenu" class="nested vertical menu">
@ -52,6 +52,11 @@
</a>
</router-link>
</ul>
<add-label-modal
v-if="showAddLabel"
:show.sync="showAddLabel"
:on-close="hideAddLabelPopup"
/>
</router-link>
</template>
@ -61,8 +66,17 @@ import { mapGetters } from 'vuex';
import router from '../../routes';
import adminMixin from '../../mixins/isAdmin';
import { getInboxClassByType } from 'dashboard/helper/inbox';
import AddLabelModal from '../../routes/dashboard/settings/labels/AddLabel';
export default {
components: {
AddLabelModal,
},
mixins: [adminMixin],
data() {
return {
showAddLabel: false,
};
},
props: {
menuItem: {
type: Object,
@ -108,12 +122,24 @@ export default {
if (!child.truncateLabel) return false;
return child.label;
},
newLinkClick() {
router.push({ name: 'settings_inbox_new', params: { page: 'new' } });
newLinkClick(item) {
if (item.newLinkRouteName) {
router.push({ name: item.newLinkRouteName, params: { page: 'new' } });
} else if (item.showModalForNewItem) {
if (item.modalName === 'AddLabel') {
this.showAddLabelPopup();
}
}
},
showItem(item) {
return this.isAdmin && item.newLink !== undefined;
},
showAddLabelPopup() {
this.showAddLabel = true;
},
hideAddLabelPopup() {
this.showAddLabel = false;
},
},
};
</script>

View file

@ -3,11 +3,13 @@ import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import VueI18n from 'vue-i18n';
import WootButton from 'dashboard/components/ui/WootButton';
import i18n from 'dashboard/i18n';
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(VueI18n);
localVue.component('woot-button', WootButton);
const i18nConfig = new VueI18n({
locale: 'en',

View file

@ -4,7 +4,7 @@ import SidemenuIcon from '../SidemenuIcon';
describe('SidemenuIcon', () => {
test('matches snapshot', () => {
const wrapper = mount(SidemenuIcon);
expect(wrapper.isVueInstance()).toBeTruthy();
expect(wrapper.vm).toBeTruthy();
expect(wrapper.element).toMatchSnapshot();
});
});

View file

@ -0,0 +1,149 @@
<template>
<div :class="labelClass" :style="labelStyle" :title="description">
<i v-if="icon" class="label--icon" :class="icon" @click="onClick" />
<span v-if="!href">{{ title }}</span>
<a v-else :href="href" :style="anchorStyle">{{ title }}</a>
<i v-if="showClose" class="close--icon ion-close" @click="onClick" />
</div>
</template>
<script>
import { getContrastingTextColor } from 'shared/helpers/ColorHelper';
export default {
props: {
title: {
type: String,
required: true,
},
description: {
type: String,
default: '',
},
href: {
type: String,
default: '',
},
bgColor: {
type: String,
default: '',
},
small: {
type: Boolean,
default: false,
},
showClose: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: '',
},
colorScheme: {
type: String,
default: '',
},
},
computed: {
textColor() {
return getContrastingTextColor(this.bgColor);
},
labelClass() {
return `label ${this.colorScheme} ${this.small ? 'small' : ''}`;
},
labelStyle() {
if (this.bgColor) {
return { background: this.bgColor, color: this.textColor };
}
return {};
},
anchorStyle() {
if (this.bgColor) {
return { color: this.textColor };
}
return {};
},
},
methods: {
onClick() {
this.$emit('click', this.title);
},
},
};
</script>
<style scoped lang="scss">
@import '~dashboard/assets/scss/variables';
.label {
font-weight: var(--font-weight-medium);
margin-right: var(--space-smaller);
margin-bottom: var(--space-smaller);
&.small {
font-size: var(--font-size-micro);
}
.label--icon {
cursor: pointer;
}
.label--icon,
.close--icon {
font-size: var(--font-size-micro);
cursor: pointer;
}
&.small .label--icon,
&.small .close--icon {
font-size: var(--font-size-nano);
}
a {
font-size: var(--font-size-mini);
&:hover {
text-decoration: underline;
}
}
/* Color Schemes */
&.primary {
background: var(--w-100);
color: var(--w-900);
border: 1px solid var(--w-200);
a {
color: var(--w-900);
}
}
&.secondary {
background: var(--s-100);
color: var(--s-900);
border: 1px solid var(--s-200);
a {
color: var(--s-900);
}
}
&.success {
background: var(--g-100);
color: var(--g-900);
border: 1px solid var(--g-200);
a {
color: var(--g-900);
}
}
&.alert {
background: var(--r-100);
color: var(--r-900);
border: 1px solid var(--r-200);
a {
color: var(--r-900);
}
}
&.warning {
background: var(--y-100);
color: var(--y-900);
border: 1px solid var(--y-300);
a {
color: var(--y-900);
}
}
}
</style>

View file

@ -0,0 +1,50 @@
import { action } from '@storybook/addon-actions';
import WootButton from '../WootButton.vue';
export default {
title: 'Components/Button',
component: WootButton,
argTypes: {
colorScheme: {
control: {
type: 'select',
options: ['primary', 'secondary', 'success', 'alert', 'warning'],
},
},
size: {
control: {
type: 'select',
options: ['tiny', 'small', 'medium', 'large', 'expanded'],
},
},
variant: {
control: {
type: 'select',
options: ['hollow', 'clear'],
},
},
isLoading: {
control: {
type: 'boolean',
},
},
isDisabled: {
control: {
type: 'boolean',
},
},
},
};
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { WootButton },
template:
'<woot-button v-bind="$props" @click="onClick">{{label}}</woot-button>',
});
export const Primary = Template.bind({});
Primary.args = {
label: 'New message',
onClick: action('Hello'),
};

View file

@ -0,0 +1,64 @@
import { action } from '@storybook/addon-actions';
export default {
title: 'Components/Label',
argTypes: {
title: {
defaultValue: 'sales',
control: {
type: 'text',
},
},
colorScheme: {
control: {
type: 'select',
options: ['primary', 'secondary', 'success', 'alert', 'warning'],
},
},
description: {
defaultValue: 'label',
control: {
type: 'text',
},
},
href: {
control: {
type: 'text',
},
},
bgColor: {
defaultValue: '#a83262',
control: {
type: 'text',
},
},
small: {
defaultValue: false,
control: {
type: 'boolean',
},
},
showClose: {
defaultValue: false,
control: {
type: 'boolean',
},
},
icon: {
defaultValue: 'ion-close',
control: {
type: 'text',
},
},
},
};
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
template: '<woot-label v-bind="$props" @click="onClick"></woot-label>',
});
export const DefaultLabel = Template.bind({});
DefaultLabel.args = {
onClick: action('clicked'),
};

View file

@ -1,87 +0,0 @@
<template>
<div
:class="labelClass"
:style="{ background: bgColor, color: textColor }"
:title="description"
>
<span v-if="!href">{{ title }}</span>
<a v-else :href="href" :style="{ color: textColor }">{{ title }}</a>
<i v-if="showIcon" class="label--icon" :class="icon" @click="onClick" />
</div>
</template>
<script>
import { getContrastingTextColor } from 'shared/helpers/ColorHelper';
export default {
props: {
title: {
type: String,
required: true,
},
description: {
type: String,
default: '',
},
href: {
type: String,
default: '',
},
bgColor: {
type: String,
default: '#1f93ff',
},
small: {
type: Boolean,
default: false,
},
showIcon: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: 'ion-close',
},
},
computed: {
textColor() {
return getContrastingTextColor(this.bgColor);
},
labelClass() {
return `label ${this.small ? 'small' : ''}`;
},
},
methods: {
onClick() {
this.$emit('click', this.title);
},
},
};
</script>
<style scoped lang="scss">
@import '~dashboard/assets/scss/variables';
.label {
display: inline-block;
font-size: $font-size-small;
line-height: 1;
margin: $space-micro;
&.small {
font-size: $font-size-mini;
}
a {
&:hover {
text-decoration: underline;
}
}
}
.label--icon {
cursor: pointer;
font-size: $font-size-micro;
line-height: 1.5;
margin-left: $space-smaller;
}
</style>

View file

@ -12,39 +12,41 @@
v-if="totalCount"
class="primary button-group pagination-button-group"
>
<button
class="button small goto-first"
:class="firstPageButtonClass"
<woot-button
size="small"
class-names="goto-first"
:is-disabled="hasFirstPage"
@click="onFirstPage"
>
<i class="ion-chevron-left" />
<i class="ion-chevron-left" />
</button>
<button
class="button small"
:class="prevPageButtonClass"
</woot-button>
<woot-button
size="small"
:is-disabled="hasPrevPage"
@click="onPrevPage"
>
<i class="ion-chevron-left" />
</button>
<button class="button" @click.prevent>
</woot-button>
<woot-button @click.prevent>
{{ currentPage }}
</button>
<button
class="button small"
:class="nextPageButtonClass"
</woot-button>
<woot-button
size="small"
:is-disabled="hasNextPage"
@click="onNextPage"
>
<i class="ion-chevron-right" />
</button>
<button
class="button small goto-last"
:class="lastPageButtonClass"
</woot-button>
<woot-button
size="small"
class-names="goto-last"
:is-disabled="hasLastPage"
@click="onLastPage"
>
<i class="ion-chevron-right" />
<i class="ion-chevron-right" />
</button>
</woot-button>
</div>
</div>
</footer>
@ -91,35 +93,19 @@ export default {
this.currentPage === Math.ceil(this.totalCount / this.pageSize);
return isDisabled;
},
lastPageButtonClass() {
const className = this.hasLastPage ? 'disabled' : '';
return className;
},
hasFirstPage() {
const isDisabled = this.currentPage === 1;
return isDisabled;
},
firstPageButtonClass() {
const className = this.hasFirstPage ? 'disabled' : '';
return className;
},
hasNextPage() {
const isDisabled =
this.currentPage === Math.ceil(this.totalCount / this.pageSize);
return isDisabled;
},
nextPageButtonClass() {
const className = this.hasNextPage ? 'disabled' : '';
return className;
},
hasPrevPage() {
const isDisabled = this.currentPage === 1;
return isDisabled;
},
prevPageButtonClass() {
const className = this.hasPrevPage ? 'disabled' : '';
return className;
},
},
methods: {
onNextPage() {

View file

@ -14,12 +14,12 @@ const chartOptions = {
scales: {
xAxes: [
{
barPercentage: 1.26,
barPercentage: 1.1,
ticks: {
fontFamily,
},
gridLines: {
display: false,
drawOnChartArea: false,
},
},
],
@ -30,7 +30,7 @@ const chartOptions = {
beginAtZero: true,
},
gridLines: {
display: false,
drawOnChartArea: false,
},
},
],

View file

@ -0,0 +1,29 @@
<template>
<div :class="`status-badge status-badge__${status}`" />
</template>
<script>
export default {
props: {
status: { type: String, default: '' },
},
};
</script>
<style lang="scss" scoped>
@import '~dashboard/assets/scss/variables';
.status-badge {
width: var(--space-one);
height: var(--space-one);
margin-right: var(--space-micro);
display: inline-block;
border-radius: 50%;
&__online {
background: var(--g-400);
}
&__offline {
background: var(--b-600);
}
&__busy {
background: var(--y-700);
}
}
</style>

View file

@ -63,7 +63,7 @@ export default {
watch: {
'currentChat.inbox_id'(inboxId) {
if (inboxId) {
this.$store.dispatch('inboxMembers/fetch', { inboxId });
this.$store.dispatch('inboxAssignableAgents/fetch', { inboxId });
}
},
},
@ -80,6 +80,7 @@ export default {
.conversation-details-wrap {
display: flex;
flex-direction: column;
min-width: 0;
width: 100%;
border-left: 1px solid var(--color-border);
background: var(--color-background-light);

View file

@ -30,11 +30,13 @@
<span v-if="lastMessageInChat.content">
{{ parsedLastMessage }}
</span>
<span v-else-if="!lastMessageInChat.attachments">{{ ` ` }}</span>
<span v-else>
<span v-else-if="lastMessageInChat.attachments">
<i :class="`small-icon ${this.$t(`${attachmentIconKey}.ICON`)}`"></i>
{{ this.$t(`${attachmentIconKey}.CONTENT`) }}
</span>
<span v-else>
{{ $t('CHAT_LIST.NO_CONTENT') }}
</span>
</p>
<p v-else class="conversation--message">
<i class="ion-android-alert"></i>

View file

@ -46,6 +46,14 @@
@select="assignAgent"
@remove="removeAgent"
>
<template slot="option" slot-scope="props">
<div class="option__desc">
<availability-status-badge
:status="props.option.availability_status"
/>
<span class="option__title">{{ props.option.name }}</span>
</div>
</template>
<span slot="noResult">{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}</span>
</multiselect>
</div>
@ -57,11 +65,13 @@
import { mapGetters } from 'vuex';
import MoreActions from './MoreActions';
import Thumbnail from '../Thumbnail';
import AvailabilityStatusBadge from '../conversation/AvailabilityStatusBadge';
export default {
components: {
MoreActions,
Thumbnail,
AvailabilityStatusBadge,
},
props: {
@ -83,8 +93,8 @@ export default {
computed: {
...mapGetters({
getAgents: 'inboxMembers/getMembersByInbox',
uiFlags: 'inboxMembers/getUIFlags',
getAgents: 'inboxAssignableAgents/getAssignableAgents',
uiFlags: 'inboxAssignableAgents/getUIFlags',
currentChat: 'getSelectedChat',
}),
@ -126,7 +136,6 @@ export default {
bus.$emit('newToastMessage', this.$t('CONVERSATION.CHANGE_AGENT'));
});
},
removeAgent() {},
},
};
@ -142,4 +151,17 @@ export default {
.conv-header {
flex: 0 0 var(--space-jumbo);
}
.option__desc {
display: flex;
align-items: center;
}
.option__desc {
&::v-deep .status-badge {
margin-right: var(--space-small);
min-width: 0;
flex-shrink: 0;
}
}
</style>

View file

@ -109,12 +109,14 @@ export default {
);
const {
email: { html_content: { full: fullHTMLContent } = {} } = {},
email: {
html_content: { full: fullHTMLContent, reply: replyHTMLContent } = {},
} = {},
} = this.contentAttributes;
if (fullHTMLContent && this.isIncoming) {
if ((replyHTMLContent || fullHTMLContent) && this.isIncoming) {
let parsedContent = new DOMParser().parseFromString(
fullHTMLContent || '',
replyHTMLContent || fullHTMLContent || '',
'text/html'
);
if (!parsedContent.getElementsByTagName('parsererror').length) {

View file

@ -186,10 +186,12 @@ export default {
if (this.isPrivate) {
return MESSAGE_MAX_LENGTH.GENERAL;
}
if (this.isAFacebookInbox) {
return MESSAGE_MAX_LENGTH.FACEBOOK;
}
if (this.isATwilioWhatsappChannel) {
return MESSAGE_MAX_LENGTH.TWILIO_WHATSAPP;
}
if (this.isATwilioSMSChannel) {
return MESSAGE_MAX_LENGTH.TWILIO_SMS;
}

View file

@ -10,8 +10,7 @@ class ActionCableConnector extends BaseActionCableConnector {
'message.created': this.onMessageCreated,
'message.updated': this.onMessageUpdated,
'conversation.created': this.onConversationCreated,
'conversation.opened': this.onStatusChange,
'conversation.resolved': this.onStatusChange,
'conversation.status_changed': this.onStatusChange,
'user:logout': this.onLogout,
'page:reload': this.onReload,
'assignee.changed': this.onAssigneeChanged,

View file

@ -8,6 +8,7 @@ export const getSidebarItems = accountId => ({
'inbox_conversation',
'conversation_through_inbox',
'contacts_dashboard',
'contacts_dashboard_manage',
'notifications_dashboard',
'settings_account_reports',
'profile_settings',

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "إلغاء",
"CREATE_BUTTON_TEXT": "إنشاء",
"FORM": {
"TITLE": {
"LABEL": "Title",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "رسالة",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "أرسلت بواسطة",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "الرجاء إدخال عنوان URL صالح"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "تحديث",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "حدث خطأ، الرجاء المحاولة مرة أخرى"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Title",
"MESSAGE": "رسالة",
"STATUS": "الحالة",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "Add",
"EDIT": "تعديل",
"DELETE": "حذف"
},
"STATUS": {
"ENABLED": "مفعل",
"DISABLED": "معطّل"
},
"SENDER": {
"BOT": "رد آلي"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "تم تلقيه عبر البريد الإلكتروني",
"VIEW_TWEET_IN_TWITTER": "عرض التغريدة في تويتر",
"REPLY_TO_TWEET": "الرد على هذه التغريدة",
"NO_MESSAGES": "لا توجد رسائل"
"NO_MESSAGES": "لا توجد رسائل",
"NO_CONTENT": "No content available"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "الوسوم المتاحة في الحساب",
"REMOVE": "انقر على أيقونة X لإزالة الوسم",
"ADD": "اضغط على أيقونة + لإضافة وسوم",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "تحديث الوسوم",
"UPDATE_ERROR": "تعذر تحديث الوسوم، الرجاء المحاولة مرة أخرى."
},
"NO_LABELS_TO_ADD": "لا يوجد وسوم في الحساب.",
"NO_AVAILABLE_LABELS": "لا يوجد وسوم مضافة لهذه المحادثة."
"NO_AVAILABLE_LABELS": "لا يوجد وسوم مضافة لهذه المحادثة.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "كتم المحادثة",
"UNMUTE_CONTACT": "إلغاء كتم المحادثة",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "عرض التفاصيل"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notes"
},
"ADD": {
"BUTTON": "Add",
"PLACEHOLDER": "Add a note",
"TITLE": "Shift + Enter to create a note"
},
"FOOTER": {
"BUTTON": "View all notes"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "الإعدادات",
"COLLABORATORS": "المتعاونون",
"CONFIGURATION": "الإعدادات",
"CAMPAIGN": "Campaigns",
"PRE_CHAT_FORM": "نموذج ما قبل الدردشة",
"BUSINESS_HOURS": "ساعات العمل"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "آخر 30 يوماً"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "Cancel·la",
"CREATE_BUTTON_TEXT": "Crear",
"FORM": {
"TITLE": {
"LABEL": "Title",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "Missatge",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "Enviat per",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "Introduïu una URL vàlid"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "Actualitza",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "S'ha produït un error; tornau-ho a provar"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Title",
"MESSAGE": "Missatge",
"STATUS": "Estat",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "Add",
"EDIT": "Edita",
"DELETE": "Esborrar"
},
"STATUS": {
"ENABLED": "Habilita",
"DISABLED": "Inhabilita"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Rebut per correu electrònic",
"VIEW_TWEET_IN_TWITTER": "Veure el tuit a Twitter",
"REPLY_TO_TWEET": "Respon a aquest tuit",
"NO_MESSAGES": "Cap Missatge"
"NO_MESSAGES": "Cap Missatge",
"NO_CONTENT": "No content available"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Etiquetes disponibles al compte",
"REMOVE": "Fes clic a la icona X per eliminar l'etiqueta",
"ADD": "Fes clic a la icona + per afegir l'etiqueta",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "Actualitza les etiquetes",
"UPDATE_ERROR": "No s'han pogut actualitzar les etiquetes, torna-ho a provar."
},
"NO_LABELS_TO_ADD": "No hi ha cap etiqueta definida al compte.",
"NO_AVAILABLE_LABELS": "No hi ha etiquetes afegides a aquesta conversa."
"NO_AVAILABLE_LABELS": "No hi ha etiquetes afegides a aquesta conversa.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "Silencia la conversa",
"UNMUTE_CONTACT": "Desactiva el silenci de la conversa",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "View details"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notes"
},
"ADD": {
"BUTTON": "Add",
"PLACEHOLDER": "Add a note",
"TITLE": "Shift + Enter to create a note"
},
"FOOTER": {
"BUTTON": "View all notes"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Configuracions",
"COLLABORATORS": "Col·laboradors",
"CONFIGURATION": "Configuració",
"CAMPAIGN": "Campaigns",
"PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Últims 30 dies"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "Zrušit",
"CREATE_BUTTON_TEXT": "Create",
"FORM": {
"TITLE": {
"LABEL": "Title",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "Zpráva",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "Odeslal",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "Zadejte prosím platnou URL"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "Aktualizovat",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "Došlo k chybě, zkuste to prosím znovu"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Title",
"MESSAGE": "Zpráva",
"STATUS": "Stav",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "Add",
"EDIT": "Upravit",
"DELETE": "Vymazat"
},
"STATUS": {
"ENABLED": "Povoleno",
"DISABLED": "Zakázáno"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Obdrženo e-mailem",
"VIEW_TWEET_IN_TWITTER": "Zobrazit tweet na Twitteru",
"REPLY_TO_TWEET": "Odpovědět na tento tweet",
"NO_MESSAGES": "Žádné zprávy"
"NO_MESSAGES": "Žádné zprávy",
"NO_CONTENT": "No content available"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Štítky dostupné v účtu",
"REMOVE": "Kliknutím na ikonu X odstraníte štítek",
"ADD": "Kliknutím na ikonu + přidáte štítek",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "Aktualizovat štítky",
"UPDATE_ERROR": "Nelze aktualizovat štítky, zkuste to znovu."
},
"NO_LABELS_TO_ADD": "V účtu nejsou definovány žádné další štítky.",
"NO_AVAILABLE_LABELS": "Do této konverzace nebyly přidány žádné štítky."
"NO_AVAILABLE_LABELS": "Do této konverzace nebyly přidány žádné štítky.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "Ztlumit konverzaci",
"UNMUTE_CONTACT": "Zrušit ztlumení konverzace",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "Zobrazit detaily"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notes"
},
"ADD": {
"BUTTON": "Add",
"PLACEHOLDER": "Add a note",
"TITLE": "Shift + Enter to create a note"
},
"FOOTER": {
"BUTTON": "View all notes"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Nastavení",
"COLLABORATORS": "Spolupracující",
"CONFIGURATION": "Nastavení",
"CAMPAIGN": "Campaigns",
"PRE_CHAT_FORM": "Formulář před chatem",
"BUSINESS_HOURS": "Pracovní doba"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Posledních 30 dní"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "Annuller",
"CREATE_BUTTON_TEXT": "Opret",
"FORM": {
"TITLE": {
"LABEL": "Title",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "Sent by",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "Angiv en gyldig URL"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "Opdater",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "Der opstod en fejl. Prøv venligst igen"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Title",
"MESSAGE": "Message",
"STATUS": "Status",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "Add",
"EDIT": "Rediger",
"DELETE": "Slet"
},
"STATUS": {
"ENABLED": "Aktiveret",
"DISABLED": "Deaktiveret"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Modtaget via e-mail",
"VIEW_TWEET_IN_TWITTER": "Se tweet på Twitter",
"REPLY_TO_TWEET": "Svar på dette tweet",
"NO_MESSAGES": "No Messages"
"NO_MESSAGES": "No Messages",
"NO_CONTENT": "No content available"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Etiketter tilgængelige på kontoen",
"REMOVE": "Klik på X-ikonet for at fjerne etiketten",
"ADD": "Klik på + ikonet for at tilføje etiketten",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "Opdater etiketter",
"UPDATE_ERROR": "Etiketter kunne ikke opdateres. Prøv igen."
},
"NO_LABELS_TO_ADD": "Der er ikke defineret flere etiketter på kontoen.",
"NO_AVAILABLE_LABELS": "Der er ingen etiketter tilføjet til denne samtale."
"NO_AVAILABLE_LABELS": "Der er ingen etiketter tilføjet til denne samtale.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "Gør Samtale Lydløs",
"UNMUTE_CONTACT": "Fjern Lydløs",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "View details"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notes"
},
"ADD": {
"BUTTON": "Add",
"PLACEHOLDER": "Add a note",
"TITLE": "Shift + Enter to create a note"
},
"FOOTER": {
"BUTTON": "View all notes"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Indstillinger",
"COLLABORATORS": "Samarbejdspartnere",
"CONFIGURATION": "Konfiguration",
"CAMPAIGN": "Campaigns",
"PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Seneste 30 dage"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Kampagnen",
"SIDEBAR_TXT": "Proaktive Nachrichten erlauben dem Kunden, ausgehende Nachrichten an seine Kontakte zu senden, was weitere Unterhaltungen auslösen würde. Klicke auf <b>Kampagne hinzufügen</b> um eine neue Kampagne zu erstellen. Sie können auch eine bestehende Kampagne bearbeiten oder löschen, indem Sie auf die Schaltfläche Bearbeiten oder Löschen klicken.",
"HEADER_BTN_TXT": "Kampagne erstellen",
"ADD": {
"TITLE": "Kampagne erstellen",
"DESC": "Proaktive Nachrichten erlauben dem Kunden, ausgehende Nachrichten an seine Kontakte zu senden, was weitere Unterhaltungen auslösen würde.",
"CANCEL_BUTTON_TEXT": "Stornieren",
"CREATE_BUTTON_TEXT": "Erstellen",
"FORM": {
"TITLE": {
"LABEL": "Titel",
"PLACEHOLDER": "Bitte geben Sie den Titel der Kampagne ein",
"ERROR": "Titel ist erforderlich"
},
"MESSAGE": {
"LABEL": "Nachricht",
"PLACEHOLDER": "Bitte geben Sie die Nachricht der Kampagne ein",
"ERROR": "Nachricht ist erforderlich"
},
"SENT_BY": {
"LABEL": "Gesendet von",
"PLACEHOLDER": "Bitte wählen Sie den Inhalt der Kampagne aus",
"ERROR": "Absender ist erforderlich"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Bitte URL eingeben",
"ERROR": "Bitte geben Sie eine gültige URL ein"
},
"TIME_ON_PAGE": {
"LABEL": "Zeit auf Seite (Sekunden)",
"PLACEHOLDER": "Bitte die Uhrzeit eingeben",
"ERROR": "Uhrzeit auf Seite ist erforderlich"
},
"ENABLED": "Kampagne aktivieren",
"SUBMIT": "Kampagne hinzufügen"
},
"API": {
"SUCCESS_MESSAGE": "Kampagne erfolgreich erstellt",
"ERROR_MESSAGE": "Es ist ein Fehler aufgetreten, bitte versuchen Sie es erneut."
}
},
"EDIT": {
"TITLE": "Kampagne bearbeiten",
"UPDATE_BUTTON_TEXT": "Aktualisieren",
"API": {
"SUCCESS_MESSAGE": "Kampagne erfolgreich aktualisiert",
"ERROR_MESSAGE": "Es ist ein Fehler aufgetreten, bitte versuchen Sie es erneut"
}
},
"LIST": {
"LOADING_MESSAGE": "Lade Kampagnen...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Titel",
"MESSAGE": "Nachricht",
"STATUS": "Status",
"SENDER": "Absender",
"URL": "URL",
"TIME_ON_PAGE": "Zeit (Sekunden)",
"CREATED_AT": "Erstellt am"
},
"BUTTONS": {
"ADD": "Hinzufügen",
"EDIT": "Bearbeiten",
"DELETE": "Löschen"
},
"STATUS": {
"ENABLED": "Aktiviert",
"DISABLED": "Behindert"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Per E-Mail empfangen",
"VIEW_TWEET_IN_TWITTER": "Tweet auf Twitter anzeigen",
"REPLY_TO_TWEET": "Auf diesen Tweet antworten",
"NO_MESSAGES": "Keine Nachrichten"
"NO_MESSAGES": "Keine Nachrichten",
"NO_CONTENT": "Kein Inhalt verfügbar"
}
}

View file

@ -12,7 +12,7 @@
"INITIATED_FROM": "Initiiert von",
"INITIATED_AT": "Initiiert bei",
"IP_ADDRESS": "IP-Adresse",
"NEW_MESSAGE": "New message",
"NEW_MESSAGE": "Neue Nachricht",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "Es sind keine vorherigen Gespräche mit diesem Kontakt verbunden.",
"TITLE": "Vorherige Gespräche"
@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Verfügbare Labels im Konto",
"REMOVE": "Klicken Sie auf das X-Symbol, um das Label zu entfernen",
"ADD": "Klicken Sie auf das + Symbol, um ein Label hinzuzufügen",
"ADD_BUTTON": "Label hinzufügen",
"UPDATE_BUTTON": "Labels aktualisieren",
"UPDATE_ERROR": "Etiketten konnten nicht aktualisiert werden. Versuchen Sie es erneut."
},
"NO_LABELS_TO_ADD": "Es sind keine weiteren Labels im Konto definiert.",
"NO_AVAILABLE_LABELS": "Zu dieser Unterhaltung wurden noch keine Labels hinzugefügt."
"NO_AVAILABLE_LABELS": "Zu dieser Unterhaltung wurden noch keine Labels hinzugefügt.",
"LABEL_SELECT": {
"TITLE": "Label hinzufügen",
"PLACEHOLDER": "Labels suchen",
"NO_RESULT": "Keine Labels gefunden"
}
},
"MUTE_CONTACT": "Unterhaltung stummschalten",
"UNMUTE_CONTACT": "Unterhaltung entmuten",
@ -73,8 +79,8 @@
"PHONE_NUMBER": {
"PLACEHOLDER": "Geben Sie die Telefonnummer des Kontakts ein",
"LABEL": "Telefonnummer",
"HELP": "Phone number should be of E.164 format eg: +1415555555 [+][country code][area code][local phone number]",
"ERROR": "Phone number should be either empty or of E.164 format"
"HELP": "Telefonnummer sollte im E.164-Format sein, z. B.: +1415555555 [+][Landesvorwahl][Landesvorwahl][Ortsvorwahl]",
"ERROR": "Telefonnummer muss leer sein oder im E.164-Format"
},
"LOCATION": {
"PLACEHOLDER": "Geben Sie den Standort des Kontakts ein",
@ -108,27 +114,27 @@
"ERROR_MESSAGE": "Es ist ein Fehler aufgetreten, bitte versuche es erneut"
},
"NEW_CONVERSATION": {
"BUTTON_LABEL": "Start conversation",
"BUTTON_LABEL": "Gespräch starten",
"TITLE": "Neue Unterhaltung",
"DESC": "Start a new conversation by sending a new message.",
"NO_INBOX": "Couldn't find an inbox to initiate a new conversation with this contact.",
"DESC": "Starte eine Unterhaltung mit einer neuen Nachricht",
"NO_INBOX": "Konnte keinen Posteingang finden, um eine neue Unterhaltung mit diesem Kontakt zu starten.",
"FORM": {
"TO": {
"LABEL": "To"
"LABEL": "An"
},
"INBOX": {
"LABEL": "Inbox",
"ERROR": "Select an inbox"
"LABEL": "Posteingang",
"ERROR": "Posteingang auswählen"
},
"MESSAGE": {
"LABEL": "Nachricht",
"PLACEHOLDER": "Write your message here",
"ERROR": "Message can't be empty"
"PLACEHOLDER": "Schreiben Sie Ihre Nachricht hier",
"ERROR": "Nachricht darf nicht leer sein"
},
"SUBMIT": "Send message",
"SUBMIT": "Nachricht senden",
"CANCEL": "Stornieren",
"SUCCESS_MESSAGE": "Message sent!",
"ERROR_MESSAGE": "Couldn't send! try again"
"SUCCESS_MESSAGE": "Nachricht gesendet!",
"ERROR_MESSAGE": "Senden fehlgeschlagen! Bitte erneut versuchen"
}
},
"CONTACTS_PAGE": {
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "Details anzeigen"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notizen"
},
"ADD": {
"BUTTON": "Hinzufügen",
"PLACEHOLDER": "Notiz hinzufügen",
"TITLE": "Shift + Enter um eine Notiz zu erstellen"
},
"FOOTER": {
"BUTTON": "Alle Notizen anzeigen"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Einstellungen",
"COLLABORATORS": "Mitarbeitende",
"CONFIGURATION": "Konfiguration",
"CAMPAIGN": "Kampagnen",
"PRE_CHAT_FORM": "Pre-Chat-Formular",
"BUSINESS_HOURS": "Öffnungszeiten"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Letzte 30 Tage"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -43,7 +43,7 @@
},
"AGENTS": {
"BUTTON_TEXT": "Agenten im Team aktualisieren",
"TITLE": "Agenten zu Team hinzufügen - %{teamName}",
"TITLE": "Agenten zu Team %{teamName} hinzufügen",
"DESC": "Fügen Sie Agenten zu Ihrem neu erstellten Team hinzu. Alle hinzugefügten Agenten werden benachrichtigt, wenn diesem Team eine Unterhaltung zugewiesen wird."
},
"WIZARD": [
@ -77,8 +77,8 @@
"SELECTED_COUNT": "%{selected} von %{total} Agenten ausgewählt."
},
"ADD": {
"TITLE": "Agenten zu Team hinzufügen - %{teamName}",
"DESC": "Fügen Sie Agenten zu Ihrem neu erstellten Team hinzu. So können Sie bei Gesprächen als Team zusammenarbeiten, erhalten Sie Benachrichtigungen über neue Ereignisse in der gleichen Unterhaltung.",
"TITLE": "Agenten zu Team %{teamName} hinzufügen",
"DESC": "Fügen Sie Agenten zu Ihrem neu erstellten Team hinzu. So können Sie bei Gesprächen als Team zusammenarbeiten und erhalten Benachrichtigungen über neue Ereignisse in der gleichen Unterhaltung.",
"SELECT": "auswählen",
"SELECT_ALL": "alle Agenten auswählen",
"SELECTED_COUNT": "%{selected} von %{total} Agenten ausgewählt.",

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Καμπάνιες",
"SIDEBAR_TXT": "Τα προληπτικά μηνύματα επιτρέπουν την αποστολή εξερχόμενων μηνυμάτων στις επαφές, που θα ενεργοποιούν περισσότερες συνομιλίες. Κάντε κλικ στο <b>Προσθήκη Καμπάνιας</b> για να δημιουργήσετε μια νέα καμπάνια. Μπορείτε επίσης να επεξεργαστείτε ή να διαγράψετε μια ήδη υπάρχουσα καμπάνια κάνοντας κλικ στο κουμπί Επεξεργασία ή Διαγραφή.",
"HEADER_BTN_TXT": "Δημιουργία Καμπάνιας",
"ADD": {
"TITLE": "Δημιουργία Καμπάνιας",
"DESC": "Τα προληπτικά μηνύματα επιτρέπουν την αποστολή εξερχόμενων μηνυμάτων στις επαφές, που θα ενεργοποιούν περισσότερες συνομιλίες.",
"CANCEL_BUTTON_TEXT": "Άκυρο",
"CREATE_BUTTON_TEXT": "Δημιουργία",
"FORM": {
"TITLE": {
"LABEL": "Τίτλος",
"PLACEHOLDER": "Παρακαλώ εισάγετε τον τίτλο της καμπάνιας",
"ERROR": "Ο τίτλος είναι απαραίτητος"
},
"MESSAGE": {
"LABEL": "Μήνυμα",
"PLACEHOLDER": "Παρακαλώ εισάγετε το μήνυμα της καμπάνιας",
"ERROR": "Το μήνυμα είναι απαραίτητο"
},
"SENT_BY": {
"LABEL": "Αποστολή από",
"PLACEHOLDER": "Παρακαλώ επιλέξτε το περιεχόμενο της καμπάνιας",
"ERROR": "Ο αποστολέας είναι απαραίτητος"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Παρακαλώ εισάγετε το URL",
"ERROR": "Παρακαλώ εισάγετε ένα έγκυρο URL"
},
"TIME_ON_PAGE": {
"LABEL": "Χρόνος στη σελίδα(δευτερόλεπτα)",
"PLACEHOLDER": "Παρακαλώ εισάγετε το χρόνο",
"ERROR": "Ο χρόνος στη σελίδα είναι απαραίτητος"
},
"ENABLED": "Ενεργοποίηση καμπάνιας",
"SUBMIT": "Προσθήκη Καμπάνιας"
},
"API": {
"SUCCESS_MESSAGE": "Η καμπάνια δημιουργήθηκε επιτυχώς",
"ERROR_MESSAGE": "Παρουσιάστηκε σφάλμα. Παρακαλώ δοκιμάστε ξανά."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "Ενημέρωση",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "Υπήρξε ένα σφάλμα, παρακαλώ προσπαθήστε ξανά"
}
},
"LIST": {
"LOADING_MESSAGE": "Φόρτωση καμπάνιας...",
"404": "Δεν υπάρχουν εκστρατείες για αυτό το κιβώτιο εισερχόμενων.",
"TABLE_HEADER": {
"TITLE": "Τίτλος",
"MESSAGE": "Μήνυμα",
"STATUS": "Κατάσταση",
"SENDER": "Αποστολέας",
"URL": "URL",
"TIME_ON_PAGE": "Χρόνος (δευτερόλεπτα)",
"CREATED_AT": "Δημιουργήθηκε στις"
},
"BUTTONS": {
"ADD": "Προσθήκη",
"EDIT": "Επεξεργασία",
"DELETE": "Διαγραφή"
},
"STATUS": {
"ENABLED": "Ενεργό",
"DISABLED": "Ανενεργό"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Παραλήφθηκε από email",
"VIEW_TWEET_IN_TWITTER": "Προβολή του tweet στο Twitter",
"REPLY_TO_TWEET": "Απάντηση στο tweet",
"NO_MESSAGES": "Κανένα Μήνυμα"
"NO_MESSAGES": "Κανένα Μήνυμα",
"NO_CONTENT": "Μη διαθέσιμο περιεχόμενο"
}
}

View file

@ -12,7 +12,7 @@
"INITIATED_FROM": "Αρχικοποίηση από",
"INITIATED_AT": "Αρχικοποίηση τις",
"IP_ADDRESS": "Διεύθυνση IP",
"NEW_MESSAGE": "New message",
"NEW_MESSAGE": "Νέο Μήνυμα",
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "Δεν υπάρχουν προηγούμενες συνομιλίες που σχετίζονται με αυτήν την επαφή.",
"TITLE": "Προηγούμενες συνομιλίες"
@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Υπάρχουν διαθέσιμες ετικέτες στον λογαριασμό",
"REMOVE": "Πατήστε στο εικονίδιο X για να απομακρύνετε την ετικέτα",
"ADD": "Πατήστε στο εικονίδιο + για να προσθέστε την ετικέτα",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "Ενημέρωση Ετικετών",
"UPDATE_ERROR": "Δεν μπορούν να ενημερωθούν οι ετικέτες, προσπαθήστε ξανά."
},
"NO_LABELS_TO_ADD": "Δεν υπάρχουν άλλες ετικέτες στον λογαριασμό.",
"NO_AVAILABLE_LABELS": "Δεν υπάρχουν προστεθεί ετικέτες στην συνομιλία."
"NO_AVAILABLE_LABELS": "Δεν υπάρχουν προστεθεί ετικέτες στην συνομιλία.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "Σίγαση Συνομιλίας",
"UNMUTE_CONTACT": "Επαναφορά Συνομιλίας",
@ -108,27 +114,27 @@
"ERROR_MESSAGE": "Υπήρξε ένα σφάλμα, παρακαλώ προσπαθήστε ξανά"
},
"NEW_CONVERSATION": {
"BUTTON_LABEL": "Start conversation",
"BUTTON_LABEL": "Έναρξη Συνομιλίας",
"TITLE": "Νέα συνομιλία",
"DESC": "Start a new conversation by sending a new message.",
"NO_INBOX": "Couldn't find an inbox to initiate a new conversation with this contact.",
"DESC": "Ξεκινήστε μια νέα συνομιλία στέλνοντας ένα νέο μήνυμα.",
"NO_INBOX": "Δεν βρέθηκε ένα κιβώτιο εισερχόμενων για να ξεκινήσει μια νέα συνομιλία με αυτήν την επαφή.",
"FORM": {
"TO": {
"LABEL": "To"
"LABEL": "Προς"
},
"INBOX": {
"LABEL": "Inbox",
"ERROR": "Select an inbox"
"LABEL": "Εισερχόμενα",
"ERROR": "Επιλέξτε ένα κιβώτιο εισερχόμενων"
},
"MESSAGE": {
"LABEL": "Μήνυμα",
"PLACEHOLDER": "Write your message here",
"ERROR": "Message can't be empty"
"PLACEHOLDER": "Γράψτε το μήνυμά σας εδώ",
"ERROR": "Το μήνυμα δεν μπορεί να είναι άδειο"
},
"SUBMIT": "Send message",
"SUBMIT": "Αποστολή μηνύματος",
"CANCEL": "Άκυρο",
"SUCCESS_MESSAGE": "Message sent!",
"ERROR_MESSAGE": "Couldn't send! try again"
"SUCCESS_MESSAGE": "Το μήνυμα στάλθηκε!",
"ERROR_MESSAGE": "Αδυναμία αποστολής! Προσπαθήστε ξανά"
}
},
"CONTACTS_PAGE": {
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "Προβολή λεπτομεριών"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Σημειώσεις"
},
"ADD": {
"BUTTON": "Προσθήκη",
"PLACEHOLDER": "Προσθήκη σημείωσης",
"TITLE": "Shift + Enter για δημιουργία σημείωσης"
},
"FOOTER": {
"BUTTON": "Εμφάνιση όλων των σημειώσεων"
}
}
}

View file

@ -92,7 +92,7 @@
"DESC": "Ενσωματώστε το Twilio και αρχίστε να υποστηρίζετε τους πελάτες σας μέσω SMS.",
"ACCOUNT_SID": {
"LABEL": "SID Λογαριασμού",
"PLACEHOLDER": "Παρακαλώ εισάγετε το SID του Λογαριασμού Twillio",
"PLACEHOLDER": "Παρακαλώ εισάγετε το SID του Λογαριασμού Twilio",
"ERROR": "Το πεδίο είναι απαραίτητο"
},
"CHANNEL_TYPE": {
@ -118,7 +118,7 @@
"TITLE": "URL επανάκλησης",
"SUBTITLE": "Πρέπει να ρυθμίσετε το callback URL στο Twilio με το URL που αναφέρεται εδώ."
},
"SUBMIT_BUTTON": "Δημιουργία Καναλιού Twillio",
"SUBMIT_BUTTON": "Δημιουργία Καναλιού Twilio",
"API": {
"ERROR_MESSAGE": "Δεν ήταν δυνατή η πιστοποίηση των διαπιστευτηρίων Twilio. Δοκιμάστε ξανά"
}
@ -227,6 +227,7 @@
"SETTINGS": "Ρυθμίσεις",
"COLLABORATORS": "Συνεργάτες",
"CONFIGURATION": "Διαμόρφωση",
"CAMPAIGN": "Καμπάνιες",
"PRE_CHAT_FORM": "Φόρμα Προ-Συνομιλίας",
"BUSINESS_HOURS": "Ώρες Εργασίας"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Τελευταίες 30 ημέρες"
},
{
"id": 2,
"name": "Τελευταίοι 3 μήνες"
},
{
"id": 3,
"name": "Τελευταίοι 6 μήνες"
},
{
"id": 4,
"name": "Τελευταίο έτος"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "Cancel",
"CREATE_BUTTON_TEXT": "Create",
"FORM": {
"TITLE": {
"LABEL": "Title",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "Message",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "Sent by",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "Please enter a valid URL"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "Update",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "There was an error, please try again"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "Title",
"MESSAGE": "Message",
"STATUS": "Status",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "Add",
"EDIT": "Edit",
"DELETE": "Delete"
},
"STATUS": {
"ENABLED": "Enabled",
"DISABLED": "Disabled"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Received via email",
"VIEW_TWEET_IN_TWITTER": "View tweet in Twitter",
"REPLY_TO_TWEET": "Reply to this tweet",
"NO_MESSAGES": "No Messages"
"NO_MESSAGES": "No Messages",
"NO_CONTENT": "No content available"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Labels available in the account",
"REMOVE": "Click on X icon to remove the label",
"ADD": "Click on + icon to add the label",
"ADD_BUTTON": "Add Labels",
"UPDATE_BUTTON": "Update labels",
"UPDATE_ERROR": "Couldn't update labels, try again."
},
"NO_LABELS_TO_ADD": "There are no more labels defined in the account.",
"NO_AVAILABLE_LABELS": "There are no labels added to this conversation."
"NO_AVAILABLE_LABELS": "There are no labels added to this conversation.",
"LABEL_SELECT": {
"TITLE": "Add Labels",
"PLACEHOLDER": "Search labels",
"NO_RESULT": "No labels found"
}
},
"MUTE_CONTACT": "Mute Conversation",
"UNMUTE_CONTACT": "Unmute Conversation",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "View details"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notes"
},
"ADD": {
"BUTTON": "Add",
"PLACEHOLDER": "Add a note",
"TITLE": "Shift + Enter to create a note"
},
"FOOTER": {
"BUTTON": "View all notes"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Settings",
"COLLABORATORS": "Collaborators",
"CONFIGURATION": "Configuration",
"CAMPAIGN": "Campaigns",
"PRE_CHAT_FORM": "Pre Chat Form",
"BUSINESS_HOURS": "Business Hours"
},

View file

@ -1,35 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Last 30 days"
},
{
"id": 2,
"name": "Last 3 months"
},
{
"id": 3,
"name": "Last 6 months"
},
{
"id": 4,
"name": "Last year"
}
]
}

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campañas",
"SIDEBAR_TXT": "Los mensajes proactivos permiten al cliente enviar mensajes a sus contactos, lo que generaría más conversaciones. Haga clic en <b>Añadir Campaña</b> para crear una nueva campaña. También puede editar o borrar una campaña existente haciendo clic en el botón de Editar o Borrar.",
"HEADER_BTN_TXT": "Crear campaña",
"ADD": {
"TITLE": "Crear campaña",
"DESC": "Los mensajes proactivos permiten al cliente enviar mensajes a sus contactos, lo que generaría más conversaciones.",
"CANCEL_BUTTON_TEXT": "Cancelar",
"CREATE_BUTTON_TEXT": "Crear",
"FORM": {
"TITLE": {
"LABEL": "Título",
"PLACEHOLDER": "Por favor escriba un título para la campaña",
"ERROR": "El título es obligatorio"
},
"MESSAGE": {
"LABEL": "Mensaje",
"PLACEHOLDER": "Por favor escriba el mensaje para la campaña",
"ERROR": "El mensaje es obligatorio"
},
"SENT_BY": {
"LABEL": "Enviado por",
"PLACEHOLDER": "Por favor seleccione el contenido de la campaña",
"ERROR": "El remitente es obligatorio"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Por favor escriba el URL",
"ERROR": "Por favor, introduzca una URL válida"
},
"TIME_ON_PAGE": {
"LABEL": "Tiempo en la página (segundos)",
"PLACEHOLDER": "Por favor escriba la hora",
"ERROR": "La hora en la página es obligatoria"
},
"ENABLED": "Habilitar campaña",
"SUBMIT": "Añadir campaña"
},
"API": {
"SUCCESS_MESSAGE": "campaña creada satisfactoriamente",
"ERROR_MESSAGE": "Se presentó un error. Por favor intente nuevamente."
}
},
"EDIT": {
"TITLE": "Editar campaña",
"UPDATE_BUTTON_TEXT": "Actualizar",
"API": {
"SUCCESS_MESSAGE": "Campaña actualizada satisfactoriamente",
"ERROR_MESSAGE": "Hubo un error, por favor inténtelo de nuevo"
}
},
"LIST": {
"LOADING_MESSAGE": "Cargando campañas...",
"404": "No hay campañas creadas en esta bandeja.",
"TABLE_HEADER": {
"TITLE": "Título",
"MESSAGE": "Mensaje",
"STATUS": "Estado",
"SENDER": "Remitente",
"URL": "URL",
"TIME_ON_PAGE": "Tiempo (segundos)",
"CREATED_AT": "Creado el"
},
"BUTTONS": {
"ADD": "Añadir",
"EDIT": "Editar",
"DELETE": "Eliminar"
},
"STATUS": {
"ENABLED": "Activado",
"DISABLED": "Deshabilitado"
},
"SENDER": {
"BOT": "Bot"
}
}
}
}

View file

@ -80,6 +80,7 @@
"RECEIVED_VIA_EMAIL": "Recibido por correo electrónico",
"VIEW_TWEET_IN_TWITTER": "Ver trino en Twitter",
"REPLY_TO_TWEET": "Responder a éste trino",
"NO_MESSAGES": "No hay mensajes"
"NO_MESSAGES": "No hay mensajes",
"NO_CONTENT": "No hay contenido disponible"
}
}

View file

@ -28,11 +28,17 @@
"INACTIVE_LABELS": "Etiquetas disponibles en la cuenta",
"REMOVE": "Haga clic en el icono X para quitar la etiqueta",
"ADD": "Haga clic en el icono + para añadir la etiqueta",
"ADD_BUTTON": "Añadir etiquetas",
"UPDATE_BUTTON": "Actualizar etiquetas",
"UPDATE_ERROR": "No se han podido actualizar las etiquetas, inténtelo de nuevo."
},
"NO_LABELS_TO_ADD": "No hay más etiquetas definidas en la cuenta.",
"NO_AVAILABLE_LABELS": "No hay etiquetas añadidas a esta conversación."
"NO_AVAILABLE_LABELS": "No hay etiquetas añadidas a esta conversación.",
"LABEL_SELECT": {
"TITLE": "Añadir etiquetas",
"PLACEHOLDER": "Buscar etiquetas",
"NO_RESULT": "No se encontraron etiquetas"
}
},
"MUTE_CONTACT": "Silenciar Conversación",
"UNMUTE_CONTACT": "Dessilenciar conversación",
@ -151,5 +157,18 @@
},
"VIEW_DETAILS": "Ver detalles"
}
},
"NOTES": {
"HEADER": {
"TITLE": "Notas"
},
"ADD": {
"BUTTON": "Añadir",
"PLACEHOLDER": "Añadir nota",
"TITLE": "Shift + Enter para crear una nota"
},
"FOOTER": {
"BUTTON": "Ver todas las notas"
}
}
}

View file

@ -11,7 +11,7 @@
"TITLE": "Buscar mensajes",
"LOADING_MESSAGE": "Cruzando datos...",
"PLACEHOLDER": "Escriba cualquier texto para buscar mensajes",
"NO_MATCHING_RESULTS": "No results found."
"NO_MATCHING_RESULTS": "No se encontraron resultados."
},
"UNREAD_MESSAGES": "Mensajes no leídos",
"UNREAD_MESSAGE": "Mensaje sin leer",
@ -57,7 +57,7 @@
"VISIBLE_TO_AGENTS": "Nota privada: solo visible para ti y tu equipo",
"CHANGE_STATUS": "Estado de la conversación cambiado",
"CHANGE_AGENT": "Conversación cambiada de asignatario",
"CHANGE_TEAM": "Conversation team changed",
"CHANGE_TEAM": "Equipo de conversación cambiado",
"FILE_SIZE_LIMIT": "El archivo excede el límite de los archivos adjuntos {MAXIMUM_FILE_UPLOAD_SIZE}",
"SENT_BY": "Enviado por:",
"ASSIGNMENT": {
@ -108,11 +108,11 @@
}
},
"CONVERSATION_SIDEBAR": {
"DETAILS_TITLE": "Conversations Details",
"ASSIGNEE_LABEL": "Assigned Agent",
"TEAM_LABEL": "Assigned Team",
"DETAILS_TITLE": "Detalles de la conversación",
"ASSIGNEE_LABEL": "Agente asignado",
"TEAM_LABEL": "Equipo asignado",
"SELECT": {
"PLACEHOLDER": "None"
"PLACEHOLDER": "Ninguna"
}
}
}

View file

@ -227,6 +227,7 @@
"SETTINGS": "Ajustes",
"COLLABORATORS": "Colaboradores",
"CONFIGURATION": "Configuración",
"CAMPAIGN": "Campañas",
"PRE_CHAT_FORM": "Pre-formulario de chat",
"BUSINESS_HOURS": "Horarios"
},

View file

@ -1,33 +1,37 @@
import { default as _agentMgmt } from './agentMgmt.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _campaign } from './campaign.json';
import { default as _cannedMgmt } from './cannedMgmt.json';
import { default as _chatlist } from './chatlist.json';
import { default as _contact } from './contact.json';
import { default as _conversation } from './conversation.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _inboxMgmt } from './inboxMgmt.json';
import { default as _integrations } from './integrations.json';
import { default as _labelsMgmt } from './labelsMgmt.json';
import { default as _login } from './login.json';
import { default as _report } from './report.json';
import { default as _resetPassword } from './resetPassword.json';
import { default as _setNewPassword } from './setNewPassword.json';
import { default as _settings } from './settings.json';
import { default as _signup } from './signup.json';
import { default as _integrations } from './integrations.json';
import { default as _generalSettings } from './generalSettings.json';
import { default as _teamsSettings } from './teamsSettings.json';
export default {
..._agentMgmt,
..._campaign,
..._cannedMgmt,
..._chatlist,
..._contact,
..._conversation,
..._generalSettings,
..._inboxMgmt,
..._integrations,
..._labelsMgmt,
..._login,
..._report,
..._labelsMgmt,
..._resetPassword,
..._setNewPassword,
..._settings,
..._signup,
..._integrations,
..._generalSettings,
..._teamsSettings,
};

View file

@ -38,6 +38,18 @@
{
"id": 1,
"name": "Últimos 30 días"
},
{
"id": 2,
"name": "Últimos 3 meses"
},
{
"id": 3,
"name": "Últimos 6 meses"
},
{
"id": 4,
"name": "Último año"
}
]
}

View file

@ -3,7 +3,7 @@
"LINK": "Ajustes del perfil",
"TITLE": "Ajustes del perfil",
"BTN_TEXT": "Actualizar perfil",
"UPDATE_SUCCESS": "Your profile has been updated successfully",
"UPDATE_SUCCESS": "Tu perfil se ha actualizado correctamente",
"PASSWORD_UPDATE_SUCCESS": "Su contraseña se ha cambiado correctamente",
"AFTER_EMAIL_CHANGED": "Su perfil ha sido actualizado con éxito, por favor inicie sesión de nuevo cuando sus credenciales de inicio de sesión se hayan cambiado",
"FORM": {
@ -19,7 +19,7 @@
"PASSWORD_SECTION": {
"TITLE": "Contraseña",
"NOTE": "Actualizar tu contraseña restablecería tus entradas en varios dispositivos.",
"BTN_TEXT": "Change password"
"BTN_TEXT": "Cambiar contraseña"
},
"ACCESS_TOKEN": {
"TITLE": "Token de acceso",

View file

@ -0,0 +1,79 @@
{
"CAMPAIGN": {
"HEADER": "Campaigns",
"SIDEBAR_TXT": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations. Click on <b>Add Campaign</b> to create a new campaign. You can also edit or delete an existing campaign by clicking on the Edit or Delete button.",
"HEADER_BTN_TXT": "Create a campaign",
"ADD": {
"TITLE": "Create a campaign",
"DESC": "Proactive messages allow the customer to send outbound messages to their contacts which would trigger more conversations.",
"CANCEL_BUTTON_TEXT": "انصراف",
"CREATE_BUTTON_TEXT": "ايجاد كردن",
"FORM": {
"TITLE": {
"LABEL": "عنوان",
"PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required"
},
"MESSAGE": {
"LABEL": "پیام",
"PLACEHOLDER": "Please enter the message of campaign",
"ERROR": "Message is required"
},
"SENT_BY": {
"LABEL": "ارسال شده توسط",
"PLACEHOLDER": "Please select the the content of campaign",
"ERROR": "Sender is required"
},
"END_POINT": {
"LABEL": "URL",
"PLACEHOLDER": "Please enter the URL",
"ERROR": "لطفا آدرس URL صحیحی وارد کنید"
},
"TIME_ON_PAGE": {
"LABEL": "Time on page(Seconds)",
"PLACEHOLDER": "Please enter the time",
"ERROR": "Time on page is required"
},
"ENABLED": "Enable campaign",
"SUBMIT": "Add Campaign"
},
"API": {
"SUCCESS_MESSAGE": "Campaign created successfully",
"ERROR_MESSAGE": "There was an error. Please try again."
}
},
"EDIT": {
"TITLE": "Edit campaign",
"UPDATE_BUTTON_TEXT": "اعمال شود",
"API": {
"SUCCESS_MESSAGE": "Campaign updated successfully",
"ERROR_MESSAGE": "خطایی پیش آمد. لطفا دوباره امتحان کنید"
}
},
"LIST": {
"LOADING_MESSAGE": "Loading campaigns...",
"404": "There are no campaigns created for this inbox.",
"TABLE_HEADER": {
"TITLE": "عنوان",
"MESSAGE": "پیام",
"STATUS": "وضعیت",
"SENDER": "Sender",
"URL": "URL",
"TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at"
},
"BUTTONS": {
"ADD": "افزودن",
"EDIT": "ویرایش",
"DELETE": "حذف"
},
"STATUS": {
"ENABLED": "فعال",
"DISABLED": "غیرفعال"
},
"SENDER": {
"BOT": "ربات"
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more