Compare commits
107
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46b91ad840 | ||
|
|
ed8b58ad10 | ||
|
|
4928f28c64 | ||
|
|
30539c27f2 | ||
|
|
12916ceca6 | ||
|
|
2e747e7fa6 | ||
|
|
a1b6b0c06c | ||
|
|
1fe3960285 | ||
|
|
c33c844039 | ||
|
|
3c952e6a4a | ||
|
|
59184122f7 | ||
|
|
381423b1ae | ||
|
|
b7c9f779ad | ||
|
|
904d76420d | ||
|
|
fa907840c7 | ||
|
|
3760f206e8 | ||
|
|
a861257f73 | ||
|
|
143299f138 | ||
|
|
232369cd5c | ||
|
|
4b40c61201 | ||
|
|
834c219b9b | ||
|
|
d0cd1c8887 | ||
|
|
682a2aea1c | ||
|
|
1dc66db516 | ||
|
|
bc04d81a5a | ||
|
|
d2c5c2f9a3 | ||
|
|
381fda270a | ||
|
|
b3c9d1f1a5 | ||
|
|
fd4376d062 | ||
|
|
a8f053921b | ||
|
|
8e15ada164 | ||
|
|
51093fd543 | ||
|
|
48e638cc56 | ||
|
|
e6dfc159ed | ||
|
|
900c2de89a | ||
|
|
29106ebc4b | ||
|
|
a579684b34 | ||
|
|
c29a9ad062 | ||
|
|
0ac015ce7a | ||
|
|
19474e0074 | ||
|
|
ce8190dacf | ||
|
|
aacf326ca1 | ||
|
|
e39c14460b | ||
|
|
5f6e17f307 | ||
|
|
4bf23adcf5 | ||
|
|
1f4d860d9d | ||
|
|
fdbb3bf4b1 | ||
|
|
c899cc825d | ||
|
|
eb972684b3 | ||
|
|
896473f03e | ||
|
|
8c43edbd50 | ||
|
|
4c4eb4bd90 | ||
|
|
88b8597e4d | ||
|
|
76fe2f9bb8 | ||
|
|
818424259f | ||
|
|
e67f8824d9 | ||
|
|
8f1a1e0905 | ||
|
|
1b6360d9d3 | ||
|
|
8b7f10fe61 | ||
|
|
4958b3e7b6 | ||
|
|
e467d15f2c | ||
|
|
d1e7e75638 | ||
|
|
4aab63b7df | ||
|
|
acf24649b0 | ||
|
|
316cf35795 | ||
|
|
52a5a59ddb | ||
|
|
22db201a08 | ||
|
|
ea7898d113 | ||
|
|
e7e14f01e4 | ||
|
|
7d6085cefd | ||
|
|
10076c6a3e | ||
|
|
1c44445088 | ||
|
|
d305c5fd0f | ||
|
|
1577288843 | ||
|
|
63b3686746 | ||
|
|
810f950e16 | ||
|
|
dd09d560d5 | ||
|
|
c60c523851 | ||
|
|
22c2235d90 | ||
|
|
35c26367da | ||
|
|
aaf4fee9a6 | ||
|
|
3c21f62485 | ||
|
|
50b2ca014e | ||
|
|
d731c972ad | ||
|
|
5845881b08 | ||
|
|
64138ef220 | ||
|
|
046ce68a45 | ||
|
|
e34ab5957f | ||
|
|
75a5492840 | ||
|
|
56fbbe92b4 | ||
|
|
dc4e13b300 | ||
|
|
2c7f93978e | ||
|
|
6e30064421 | ||
|
|
68062216e4 | ||
|
|
8a8f325f64 | ||
|
|
cf90b898f4 | ||
|
|
1f4cb0e1ca | ||
|
|
c6ecf80dff | ||
|
|
c29b77c214 | ||
|
|
c301845ade | ||
|
|
78fab7897d | ||
|
|
f48e014694 | ||
|
|
206433db32 | ||
|
|
1ddb73ea97 | ||
|
|
b5071e61d7 | ||
|
|
a80eff9aa3 | ||
|
|
a59fb90785 |
@@ -74,7 +74,7 @@ jobs:
|
||||
name: yarn
|
||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||
|
||||
# Store yarn / webpacker cache
|
||||
# Store yarn cache
|
||||
- save_cache:
|
||||
key: chatwoot-yarn-{{ .Environment.CACHE_VERSION }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# It has the dependencies already installed so that codespace will boot up fast
|
||||
FROM ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
|
||||
# Do the set up required for chatwoot app
|
||||
# Do the set up required for chatwoot app
|
||||
WORKDIR /workspace
|
||||
COPY . /workspace
|
||||
RUN yarn && gem install bundler && bundle install
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
|
||||
ARG VARIANT=ubuntu-20.04
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT}
|
||||
ARG VARIANT
|
||||
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
|
||||
|
||||
ARG NODE_VERSION
|
||||
ARG RUBY_VERSION
|
||||
ARG USER_UID
|
||||
ARG USER_GID
|
||||
|
||||
# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user.
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=$USER_UID
|
||||
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
|
||||
groupmod --gid $USER_GID vscode \
|
||||
&& usermod --uid $USER_UID --gid $USER_GID vscode \
|
||||
@@ -27,10 +31,10 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
tmux \
|
||||
zsh \
|
||||
git-flow \
|
||||
npm
|
||||
npm \
|
||||
libyaml-dev
|
||||
|
||||
# Install rbenv and ruby
|
||||
ARG RUBY_VERSION="3.2.2"
|
||||
RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \
|
||||
&& echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \
|
||||
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|
||||
@@ -46,7 +50,7 @@ RUN rbenv install $RUBY_VERSION && \
|
||||
RUN curl -L https://github.com/DarthSim/overmind/releases/download/v2.1.0/overmind-v2.1.0-linux-amd64.gz > overmind.gz \
|
||||
&& gunzip overmind.gz \
|
||||
&& sudo mv overmind /usr/local/bin \
|
||||
&& chmod +x /usr/local/bin/overmind
|
||||
&& chmod +x /usr/local/bin/overmind
|
||||
|
||||
|
||||
# Install gh
|
||||
@@ -56,7 +60,7 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | s
|
||||
&& sudo apt install gh
|
||||
|
||||
|
||||
# Do the set up required for chatwoot app
|
||||
# Do the set up required for chatwoot app
|
||||
WORKDIR /workspace
|
||||
COPY . /workspace
|
||||
|
||||
@@ -65,8 +69,7 @@ COPY Gemfile Gemfile.lock ./
|
||||
RUN gem install bundler && bundle install
|
||||
|
||||
# set up node js
|
||||
RUN npm install npm@latest -g && \
|
||||
npm install n -g && \
|
||||
n latest
|
||||
RUN npm install n -g && \
|
||||
n $NODE_VERSION
|
||||
RUN npm install --global yarn
|
||||
RUN yarn
|
||||
|
||||
@@ -1,30 +1,41 @@
|
||||
# https://github.com/microsoft/vscode-dev-containers/blob/master/containers/python-3-postgres/.devcontainer/docker-compose.yml
|
||||
# https://github.com/microsoft/vscode-dev-containers/blob/master/containers/ruby-rails/.devcontainer/devcontainer.json
|
||||
#
|
||||
#
|
||||
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
app:
|
||||
base:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile.base
|
||||
args:
|
||||
VARIANT: "ubuntu-22.04"
|
||||
NODE_VERSION: "20.9.0"
|
||||
RUBY_VERSION: "3.2.2"
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
image: base:latest
|
||||
|
||||
app:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile
|
||||
args:
|
||||
# Update 'VARIANT' to pick a Ruby version: https://github.com/microsoft/vscode-dev-containers/tree/main/containers/ruby
|
||||
VARIANT: 3
|
||||
# [Choice] Install Node.js
|
||||
INSTALL_NODE: "true"
|
||||
NODE_VERSION: "lts/*"
|
||||
VARIANT: "ubuntu-22.04"
|
||||
NODE_VERSION: "20.9.0"
|
||||
RUBY_VERSION: "3.2.2"
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: 1000
|
||||
USER_GID: 1000
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
|
||||
volumes:
|
||||
- ..:/workspace:cached
|
||||
|
||||
|
||||
# Overrides default command so things don't shut down after the process ends.
|
||||
command: sleep infinity
|
||||
|
||||
|
||||
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
|
||||
network_mode: service:db
|
||||
|
||||
@@ -49,8 +60,7 @@ services:
|
||||
restart: unless-stopped
|
||||
image: mailhog/mailhog
|
||||
network_mode: service:db
|
||||
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
|
||||
@@ -3,10 +3,10 @@ sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env
|
||||
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env
|
||||
sed -i -e '/SMTP_ADDRESS/ s/=.*/=localhost/' .env
|
||||
sed -i -e "/FRONTEND_URL/ s/=.*/=https:\/\/$CODESPACE_NAME-3000.githubpreview.dev/" .env
|
||||
sed -i -e "/WEBPACKER_DEV_SERVER_PUBLIC/ s/=.*/=https:\/\/$CODESPACE_NAME-3035.githubpreview.dev/" .env
|
||||
# uncomment the webpacker env variable
|
||||
sed -i -e '/WEBPACKER_DEV_SERVER_PUBLIC/s/^# //' .env
|
||||
# fix the error with webpacker
|
||||
sed -i -e "/DEV_SERVER_PUBLIC/ s/=.*/=https:\/\/$CODESPACE_NAME-3035.githubpreview.dev/" .env
|
||||
# uncomment the dev server env variable
|
||||
sed -i -e '/DEV_SERVER_PUBLIC/s/^# //' .env
|
||||
# fix the error with dev server
|
||||
echo 'export NODE_OPTIONS=--openssl-legacy-provider' >> ~/.zshrc
|
||||
|
||||
# codespaces make the ports public
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ ANDROID_SHA256_CERT_FINGERPRINT=AC:73:8E:DE:EB:56:EA:CC:10:87:02:A7:65:37:7B:38:
|
||||
# if you want to use letter_opener for local emails
|
||||
# LETTER_OPENER=true
|
||||
# meant to be used in github codespaces
|
||||
# WEBPACKER_DEV_SERVER_PUBLIC=
|
||||
# DEV_SERVER_PUBLIC=
|
||||
|
||||
# If you want to use official mobile app,
|
||||
# the notifications would be relayed via a Chatwoot server
|
||||
|
||||
+2
-10
@@ -7,11 +7,10 @@ module.exports = {
|
||||
'plugin:cypress/recommended',
|
||||
],
|
||||
parserOptions: {
|
||||
parser: '@babel/eslint-parser',
|
||||
ecmaVersion: 2020,
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['html', 'prettier', 'babel'],
|
||||
plugins: ['html', 'prettier'],
|
||||
rules: {
|
||||
'prettier/prettier': ['error'],
|
||||
camelcase: 'off',
|
||||
@@ -56,13 +55,6 @@ module.exports = {
|
||||
'import/extensions': ['off'],
|
||||
'no-console': 'error',
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
webpack: {
|
||||
config: 'config/webpack/resolve.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
jest: true,
|
||||
|
||||
@@ -19,5 +19,6 @@ jobs:
|
||||
|
||||
- name: Build the Codespace Base Image
|
||||
run: |
|
||||
docker build . -t ghcr.io/chatwoot/chatwoot_codespace:latest -f .devcontainer/Dockerfile.base
|
||||
docker-compose -f .devcontainer/docker-compose.yml build base
|
||||
docker tag base:latest ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
docker push ghcr.io/chatwoot/chatwoot_codespace:latest
|
||||
|
||||
+9
-1
@@ -75,4 +75,12 @@ yalc.lock
|
||||
yarn-debug.log*
|
||||
.yarn-integrity
|
||||
|
||||
/storybook-static
|
||||
/storybook-static
|
||||
|
||||
# Vite Ruby
|
||||
/public/vite*
|
||||
node_modules
|
||||
# Vite uses dotenv and suggests to ignore local-only env files. See
|
||||
# https://vitejs.dev/guide/env-and-mode.html#env-files
|
||||
*.local
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { addDecorator } from '@storybook/vue';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import VueI18n from 'vue-i18n';
|
||||
import Vuelidate from 'vuelidate';
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||
import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
|
||||
@@ -14,7 +13,6 @@ import { domPurifyConfig } from 'shared/helpers/HTMLSanitizer';
|
||||
import '../app/javascript/dashboard/assets/scss/storybook.scss';
|
||||
|
||||
Vue.use(VueI18n);
|
||||
Vue.use(Vuelidate);
|
||||
Vue.use(WootUiKit);
|
||||
Vue.use(Vuex);
|
||||
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
||||
@@ -32,7 +30,7 @@ addDecorator(() => ({
|
||||
template: '<story/>',
|
||||
i18n: i18nConfig,
|
||||
store,
|
||||
beforeCreate: function() {
|
||||
beforeCreate: function () {
|
||||
this.$root._i18n = this.$i18n;
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -39,6 +39,8 @@ gem 'rack-attack', '>= 6.7.0'
|
||||
gem 'down'
|
||||
# authentication type to fetch and send mail over oauth2.0
|
||||
gem 'gmail_xoauth'
|
||||
# Lock net-smtp to 0.3.4 to avoid issues with gmail_xoauth2
|
||||
gem 'net-smtp', '~> 0.3.4'
|
||||
# Prevent CSV injection
|
||||
gem 'csv-safe'
|
||||
|
||||
@@ -62,7 +64,7 @@ gem 'activerecord-import'
|
||||
gem 'dotenv-rails'
|
||||
gem 'foreman'
|
||||
gem 'puma'
|
||||
gem 'webpacker'
|
||||
gem 'vite_rails'
|
||||
# metrics on heroku
|
||||
gem 'barnes'
|
||||
|
||||
@@ -74,9 +76,9 @@ gem 'devise_token_auth'
|
||||
gem 'jwt'
|
||||
gem 'pundit'
|
||||
# super admin
|
||||
gem 'administrate', '>= 0.19.0'
|
||||
gem 'administrate-field-active_storage', '>= 1.0.0'
|
||||
gem 'administrate-field-belongs_to_search'
|
||||
gem 'administrate', '>= 0.20.1'
|
||||
gem 'administrate-field-active_storage', '>= 1.0.1'
|
||||
gem 'administrate-field-belongs_to_search', '>= 0.9.0'
|
||||
|
||||
##--- gems for pubsub service ---##
|
||||
# https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/
|
||||
@@ -114,7 +116,7 @@ gem 'sentry-ruby', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.14.0', require: false
|
||||
|
||||
##-- background job processing --##
|
||||
gem 'sidekiq', '>= 7.1.3'
|
||||
gem 'sidekiq', '>= 7.2.1'
|
||||
# We want cron jobs
|
||||
gem 'sidekiq-cron', '>= 1.12.0'
|
||||
|
||||
@@ -162,7 +164,7 @@ gem 'omniauth-oauth2'
|
||||
gem 'audited', '~> 5.4', '>= 5.4.1'
|
||||
|
||||
# need for google auth
|
||||
gem 'omniauth'
|
||||
gem 'omniauth', '>= 2.1.2'
|
||||
gem 'omniauth-google-oauth2'
|
||||
gem 'omniauth-rails_csrf_protection', '~> 1.0'
|
||||
|
||||
@@ -224,7 +226,7 @@ group :development, :test do
|
||||
gem 'byebug', platform: :mri
|
||||
gem 'climate_control'
|
||||
gem 'debug', '~> 1.8'
|
||||
gem 'factory_bot_rails', '>= 6.4.2'
|
||||
gem 'factory_bot_rails', '>= 6.4.3'
|
||||
gem 'listen'
|
||||
gem 'mock_redis'
|
||||
gem 'pry-rails'
|
||||
|
||||
+44
-41
@@ -105,21 +105,21 @@ GEM
|
||||
activerecord (>= 6.0, < 7.1)
|
||||
addressable (2.8.4)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
administrate (0.19.0)
|
||||
actionpack (>= 5.0)
|
||||
actionview (>= 5.0)
|
||||
activerecord (>= 5.0)
|
||||
jquery-rails (>= 4.0)
|
||||
kaminari (>= 1.0)
|
||||
administrate (0.20.1)
|
||||
actionpack (>= 6.0, < 8.0)
|
||||
actionview (>= 6.0, < 8.0)
|
||||
activerecord (>= 6.0, < 8.0)
|
||||
jquery-rails (~> 4.6.0)
|
||||
kaminari (~> 1.2.2)
|
||||
sassc-rails (~> 2.1)
|
||||
selectize-rails (~> 0.6)
|
||||
administrate-field-active_storage (1.0.0)
|
||||
administrate-field-active_storage (1.0.1)
|
||||
administrate (>= 0.2.2)
|
||||
rails (>= 7.0)
|
||||
administrate-field-belongs_to_search (0.8.0)
|
||||
administrate-field-belongs_to_search (0.9.0)
|
||||
administrate (>= 0.3, < 1.0)
|
||||
jbuilder (~> 2)
|
||||
rails (>= 4.2, < 7.1)
|
||||
rails (>= 4.2, < 7.2)
|
||||
selectize-rails (~> 0.6)
|
||||
annotate (3.2.0)
|
||||
activerecord (>= 3.2, < 8.0)
|
||||
@@ -169,7 +169,7 @@ GEM
|
||||
climate_control (1.2.0)
|
||||
coderay (1.1.3)
|
||||
commonmarker (0.23.10)
|
||||
concurrent-ruby (1.2.2)
|
||||
concurrent-ruby (1.2.3)
|
||||
connection_pool (2.4.1)
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
@@ -216,6 +216,7 @@ GEM
|
||||
railties (>= 3.2)
|
||||
down (5.4.0)
|
||||
addressable (~> 2.8)
|
||||
dry-cli (1.0.0)
|
||||
ecma-re-validator (0.4.0)
|
||||
regexp_parser (~> 2.2)
|
||||
elastic-apm (4.6.2)
|
||||
@@ -230,9 +231,9 @@ GEM
|
||||
facebook-messenger (2.0.1)
|
||||
httparty (~> 0.13, >= 0.13.7)
|
||||
rack (>= 1.4.5)
|
||||
factory_bot (6.4.2)
|
||||
factory_bot (6.4.5)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.4.2)
|
||||
factory_bot_rails (6.4.3)
|
||||
factory_bot (~> 6.4)
|
||||
railties (>= 5.0.0)
|
||||
faker (3.2.0)
|
||||
@@ -461,7 +462,7 @@ GEM
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.5)
|
||||
minitest (5.20.0)
|
||||
minitest (5.21.2)
|
||||
mock_redis (0.36.0)
|
||||
ruby2_keywords
|
||||
msgpack (1.7.0)
|
||||
@@ -472,14 +473,14 @@ GEM
|
||||
activerecord (>= 5.2)
|
||||
net-http-persistent (4.0.2)
|
||||
connection_pool (~> 2.2)
|
||||
net-imap (0.4.5)
|
||||
net-imap (0.4.9)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.4.0)
|
||||
net-smtp (0.3.4)
|
||||
net-protocol
|
||||
netrc (0.11.0)
|
||||
newrelic-sidekiq-metrics (1.6.2)
|
||||
@@ -487,15 +488,15 @@ GEM
|
||||
sidekiq
|
||||
newrelic_rpm (9.6.0)
|
||||
base64
|
||||
nio4r (2.6.0)
|
||||
nokogiri (1.15.5)
|
||||
nio4r (2.7.0)
|
||||
nokogiri (1.16.0)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.15.5-arm64-darwin)
|
||||
nokogiri (1.16.0-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.15.5-x86_64-darwin)
|
||||
nokogiri (1.16.0-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.15.5-x86_64-linux)
|
||||
nokogiri (1.16.0-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
numo-narray (0.9.2.1)
|
||||
oauth (1.1.0)
|
||||
@@ -511,7 +512,7 @@ GEM
|
||||
rack (>= 1.2, < 4)
|
||||
snaky_hash (~> 2.0)
|
||||
version_gem (~> 1.1)
|
||||
omniauth (2.1.1)
|
||||
omniauth (2.1.2)
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
@@ -553,7 +554,7 @@ GEM
|
||||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (5.0.1)
|
||||
puma (6.3.1)
|
||||
puma (6.4.2)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
@@ -568,9 +569,9 @@ GEM
|
||||
rack (>= 2.0.0)
|
||||
rack-mini-profiler (3.2.0)
|
||||
rack (>= 1.2.0)
|
||||
rack-protection (3.0.6)
|
||||
rack
|
||||
rack-proxy (0.7.6)
|
||||
rack-protection (3.1.0)
|
||||
rack (~> 2.2, >= 2.2.4)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
@@ -610,7 +611,7 @@ GEM
|
||||
ffi (~> 1.0)
|
||||
redis (5.0.6)
|
||||
redis-client (>= 0.9.0)
|
||||
redis-client (0.19.0)
|
||||
redis-client (0.19.1)
|
||||
connection_pool
|
||||
redis-namespace (1.10.0)
|
||||
redis (>= 4)
|
||||
@@ -708,7 +709,6 @@ GEM
|
||||
activerecord (>= 4)
|
||||
activesupport (>= 4)
|
||||
selectize-rails (0.12.6)
|
||||
semantic_range (3.0.0)
|
||||
sentry-rails (5.14.0)
|
||||
railties (>= 5.0)
|
||||
sentry-ruby (~> 5.14.0)
|
||||
@@ -720,11 +720,11 @@ GEM
|
||||
sexp_processor (4.17.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (7.2.0)
|
||||
sidekiq (7.2.1)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
rack (>= 2.2.4)
|
||||
redis-client (>= 0.14.0)
|
||||
redis-client (>= 0.19.0)
|
||||
sidekiq-cron (1.12.0)
|
||||
fugit (~> 1.8)
|
||||
globalid (>= 1.0.1)
|
||||
@@ -795,6 +795,13 @@ GEM
|
||||
activemodel (>= 3.2)
|
||||
mail (~> 2.5)
|
||||
version_gem (1.1.2)
|
||||
vite_rails (3.0.17)
|
||||
railties (>= 5.1, < 8)
|
||||
vite_ruby (~> 3.0, >= 3.2.2)
|
||||
vite_ruby (3.5.0)
|
||||
dry-cli (>= 0.7, < 2)
|
||||
rack-proxy (~> 0.6, >= 0.6.1)
|
||||
zeitwerk (~> 2.2)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
web-console (4.2.1)
|
||||
@@ -810,11 +817,6 @@ GEM
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
webpacker (5.4.4)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.8.1)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
@@ -840,9 +842,9 @@ DEPENDENCIES
|
||||
active_record_query_trace
|
||||
activerecord-import
|
||||
acts-as-taggable-on
|
||||
administrate (>= 0.19.0)
|
||||
administrate-field-active_storage (>= 1.0.0)
|
||||
administrate-field-belongs_to_search
|
||||
administrate (>= 0.20.1)
|
||||
administrate-field-active_storage (>= 1.0.1)
|
||||
administrate-field-belongs_to_search (>= 0.9.0)
|
||||
annotate
|
||||
attr_extras
|
||||
audited (~> 5.4, >= 5.4.1)
|
||||
@@ -870,7 +872,7 @@ DEPENDENCIES
|
||||
elastic-apm
|
||||
email_reply_trimmer
|
||||
facebook-messenger
|
||||
factory_bot_rails (>= 6.4.2)
|
||||
factory_bot_rails (>= 6.4.3)
|
||||
faker
|
||||
fcm
|
||||
flag_shih_tzu
|
||||
@@ -903,9 +905,10 @@ DEPENDENCIES
|
||||
meta_request
|
||||
mock_redis
|
||||
neighbor
|
||||
net-smtp (~> 0.3.4)
|
||||
newrelic-sidekiq-metrics (>= 1.6.2)
|
||||
newrelic_rpm
|
||||
omniauth
|
||||
omniauth (>= 2.1.2)
|
||||
omniauth-google-oauth2
|
||||
omniauth-oauth2
|
||||
omniauth-rails_csrf_protection (~> 1.0)
|
||||
@@ -939,7 +942,7 @@ DEPENDENCIES
|
||||
sentry-ruby
|
||||
sentry-sidekiq (>= 5.14.0)
|
||||
shoulda-matchers
|
||||
sidekiq (>= 7.1.3)
|
||||
sidekiq (>= 7.2.1)
|
||||
sidekiq-cron (>= 1.12.0)
|
||||
simplecov (= 0.17.1)
|
||||
slack-ruby-client (~> 2.2.0)
|
||||
@@ -956,10 +959,10 @@ DEPENDENCIES
|
||||
tzinfo-data
|
||||
uglifier
|
||||
valid_email2
|
||||
vite_rails
|
||||
web-console (>= 4.2.1)
|
||||
web-push
|
||||
webmock
|
||||
webpacker
|
||||
wisper (= 2.0.0)
|
||||
working_hours
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
backend: bin/rails s -p 3000
|
||||
frontend: export NODE_OPTIONS=--openssl-legacy-provider && bin/webpack-dev-server
|
||||
# https://github.com/mperham/sidekiq/issues/3090#issuecomment-389748695
|
||||
worker: dotenv bundle exec sidekiq -C config/sidekiq.yml
|
||||
frontend: bin/vite dev
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
backend: RAILS_ENV=test bin/rails s -p 5050
|
||||
frontend: export NODE_OPTIONS=--openssl-legacy-provider && bin/webpack-dev-server
|
||||
frontend: bin/vite
|
||||
worker: RAILS_ENV=test dotenv bundle exec sidekiq -C config/sidekiq.yml
|
||||
|
||||
@@ -118,4 +118,4 @@ Thanks goes to all these [wonderful people](https://www.chatwoot.com/docs/contri
|
||||
<a href="https://github.com/chatwoot/chatwoot/graphs/contributors"><img src="https://opencollective.com/chatwoot/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
|
||||
*Chatwoot* © 2017-2023, Chatwoot Inc - Released under the MIT License.
|
||||
*Chatwoot* © 2017-2024, Chatwoot Inc - Released under the MIT License.
|
||||
|
||||
@@ -104,7 +104,7 @@ class ContactIdentifyAction
|
||||
# TODO: replace reject { |_k, v| v.blank? } with compact_blank when rails is upgraded
|
||||
@contact.discard_invalid_attrs if discard_invalid_attrs
|
||||
@contact.save!
|
||||
Avatar::AvatarFromUrlJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present?
|
||||
Avatar::AvatarFromUrlJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present? && !@contact.avatar.attached?
|
||||
end
|
||||
|
||||
def merge_contact(base_contact, merge_contact)
|
||||
|
||||
@@ -12,6 +12,7 @@ class ContactMergeAction
|
||||
merge_conversations
|
||||
merge_messages
|
||||
merge_contact_inboxes
|
||||
merge_contact_notes
|
||||
merge_and_remove_mergee_contact
|
||||
end
|
||||
@base_contact
|
||||
@@ -33,6 +34,10 @@ class ContactMergeAction
|
||||
Conversation.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
|
||||
end
|
||||
|
||||
def merge_contact_notes
|
||||
Note.where(contact_id: @mergee_contact.id, account_id: @mergee_contact.account_id).update(contact_id: @base_contact.id)
|
||||
end
|
||||
|
||||
def merge_messages
|
||||
Message.where(sender: @mergee_contact).update(sender: @base_contact)
|
||||
end
|
||||
|
||||
@@ -86,8 +86,5 @@ $swift-ease-out-duration: .4s !default;
|
||||
$swift-ease-out-timing-function: cubic-bezier(.25, .8, .25, 1) !default;
|
||||
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
|
||||
|
||||
// Ionicons
|
||||
$ionicons-font-path: '~ionicons/fonts';
|
||||
|
||||
// Transitions
|
||||
$transition-ease-in: all 0.250s ease-in;
|
||||
|
||||
@@ -48,6 +48,10 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
@outgoing_echo ? recipient_id : sender_id
|
||||
end
|
||||
|
||||
def message_is_unsupported?
|
||||
message[:is_unsupported].present? && @messaging[:message][:is_unsupported] == true
|
||||
end
|
||||
|
||||
def sender_id
|
||||
@messaging[:sender][:id]
|
||||
end
|
||||
@@ -118,7 +122,7 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
end
|
||||
|
||||
def message_params
|
||||
{
|
||||
params = {
|
||||
account_id: conversation.account_id,
|
||||
inbox_id: conversation.inbox_id,
|
||||
message_type: message_type,
|
||||
@@ -129,6 +133,9 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
in_reply_to_external_id: message_reply_attributes
|
||||
}
|
||||
}
|
||||
|
||||
params[:content_attributes][:is_unsupported] = true if message_is_unsupported?
|
||||
params
|
||||
end
|
||||
|
||||
def already_sent_from_chatwoot?
|
||||
|
||||
@@ -2,8 +2,6 @@ class NotificationBuilder
|
||||
pattr_initialize [:notification_type!, :user!, :account!, :primary_actor!, :secondary_actor]
|
||||
|
||||
def perform
|
||||
return unless user_subscribed_to_notification?
|
||||
|
||||
build_notification
|
||||
end
|
||||
|
||||
@@ -16,7 +14,7 @@ class NotificationBuilder
|
||||
def user_subscribed_to_notification?
|
||||
notification_setting = user.notification_settings.find_by(account_id: account.id)
|
||||
# added for the case where an assignee might be removed from the account but remains in conversation
|
||||
return if notification_setting.blank?
|
||||
return false if notification_setting.blank?
|
||||
|
||||
return true if notification_setting.public_send("email_#{notification_type}?")
|
||||
return true if notification_setting.public_send("push_#{notification_type}?")
|
||||
@@ -25,6 +23,9 @@ class NotificationBuilder
|
||||
end
|
||||
|
||||
def build_notification
|
||||
# Create conversation_creation notification only if user is subscribed to it
|
||||
return if notification_type == 'conversation_creation' && !user_subscribed_to_notification?
|
||||
|
||||
user.notifications.create!(
|
||||
notification_type: notification_type,
|
||||
account: account,
|
||||
|
||||
@@ -46,6 +46,14 @@ class V2::ReportBuilder
|
||||
}
|
||||
end
|
||||
|
||||
def short_summary
|
||||
{
|
||||
conversations_count: conversations.count,
|
||||
avg_first_response_time: avg_first_response_time_summary,
|
||||
avg_resolution_time: avg_resolution_time_summary
|
||||
}
|
||||
end
|
||||
|
||||
def conversation_metrics
|
||||
if params[:type].equal?(:account)
|
||||
live_conversations
|
||||
|
||||
@@ -60,13 +60,26 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
def toggle_status
|
||||
if params[:status].present?
|
||||
# FIXME: move this logic into a service object
|
||||
if pending_to_open_by_bot?
|
||||
@conversation.bot_handoff!
|
||||
elsif params[:status].present?
|
||||
set_conversation_status
|
||||
@status = @conversation.save!
|
||||
else
|
||||
@status = @conversation.toggle_status
|
||||
end
|
||||
assign_conversation if @conversation.status == 'open' && Current.user.is_a?(User) && Current.user&.agent?
|
||||
assign_conversation if should_assign_conversation?
|
||||
end
|
||||
|
||||
def pending_to_open_by_bot?
|
||||
return false unless Current.user.is_a?(AgentBot)
|
||||
|
||||
@conversation.status == 'pending' && params[:status] == 'open'
|
||||
end
|
||||
|
||||
def should_assign_conversation?
|
||||
@conversation.status == 'open' && Current.user.is_a?(User) && Current.user&.agent?
|
||||
end
|
||||
|
||||
def toggle_priority
|
||||
|
||||
@@ -39,6 +39,8 @@ class Api::V1::Accounts::CustomAttributeDefinitionsController < Api::V1::Account
|
||||
:attribute_display_type,
|
||||
:attribute_key,
|
||||
:attribute_model,
|
||||
:regex_pattern,
|
||||
:regex_cue,
|
||||
attribute_values: []
|
||||
)
|
||||
end
|
||||
|
||||
@@ -7,9 +7,9 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
|
||||
before_action :set_current_page, only: [:index]
|
||||
|
||||
def index
|
||||
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
|
||||
@count = notifications.count
|
||||
@notifications = notifications.page(@current_page).per(RESULTS_PER_PAGE)
|
||||
@unread_count = notification_finder.unread_count
|
||||
@notifications = notification_finder.perform
|
||||
@count = notification_finder.count
|
||||
end
|
||||
|
||||
def read_all
|
||||
@@ -35,7 +35,7 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
def unread_count
|
||||
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
|
||||
@unread_count = notification_finder.unread_count
|
||||
render json: @unread_count
|
||||
end
|
||||
|
||||
@@ -61,7 +61,7 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
|
||||
@current_page = params[:page] || 1
|
||||
end
|
||||
|
||||
def notifications
|
||||
@notifications ||= current_user.notifications.where(account_id: current_account.id)
|
||||
def notification_finder
|
||||
@notification_finder ||= NotificationFinder.new(Current.user, Current.account, params)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,7 +14,14 @@ module AccessTokenAuthHelper
|
||||
render_unauthorized('Invalid Access Token') && return if @access_token.blank?
|
||||
|
||||
@resource = @access_token.owner
|
||||
Current.user = @resource if current_user.is_a?(User)
|
||||
Current.user = @resource if allowed_current_user_type?(@resource)
|
||||
end
|
||||
|
||||
def allowed_current_user_type?(resource)
|
||||
return true if resource.is_a?(User)
|
||||
return true if resource.is_a?(AgentBot)
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def validate_bot_access_token!
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class Public::Api::V1::Portals::BaseController < PublicController
|
||||
before_action :show_plain_layout
|
||||
before_action :set_color_scheme
|
||||
before_action :set_global_config
|
||||
around_action :set_locale
|
||||
after_action :allow_iframe_requests
|
||||
|
||||
@@ -60,4 +61,8 @@ class Public::Api::V1::Portals::BaseController < PublicController
|
||||
portal
|
||||
render 'public/api/v1/portals/error/404', status: :not_found
|
||||
end
|
||||
|
||||
def set_global_config
|
||||
@global_config = GlobalConfig.get('LOGO_THUMBNAIL', 'BRAND_NAME', 'BRAND_URL')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,9 @@ class SuperAdmin::AppConfigsController < SuperAdmin::ApplicationController
|
||||
.map { |name, serialized_value| [name, serialized_value['value']] }
|
||||
.to_h
|
||||
# rubocop:enable Style/HashTransformValues
|
||||
@installation_configs = ConfigLoader.new.general_configs.each_with_object({}) do |config_hash, result|
|
||||
result[config_hash['name']] = config_hash.except('name')
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
class NotificationFinder
|
||||
attr_reader :current_user, :current_account, :params
|
||||
|
||||
RESULTS_PER_PAGE = 15
|
||||
|
||||
def initialize(current_user, current_account, params = {})
|
||||
@current_user = current_user
|
||||
@current_account = current_account
|
||||
@params = params
|
||||
set_up
|
||||
end
|
||||
|
||||
def perform
|
||||
notifications
|
||||
end
|
||||
|
||||
def unread_count
|
||||
@notifications.where(read_at: nil).count
|
||||
end
|
||||
|
||||
def count
|
||||
@notifications.count
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_up
|
||||
find_all_notifications
|
||||
filter_by_status
|
||||
end
|
||||
|
||||
def find_all_notifications
|
||||
@notifications = current_user.notifications.where(account_id: @current_account.id)
|
||||
end
|
||||
|
||||
def filter_by_status
|
||||
@notifications = @notifications.where('snoozed_until > ?', DateTime.now.utc) if params[:status] == 'snoozed'
|
||||
end
|
||||
|
||||
def current_page
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
def notifications
|
||||
@notifications.page(current_page).per(RESULTS_PER_PAGE).order(last_activity_at: :desc)
|
||||
end
|
||||
end
|
||||
@@ -53,7 +53,7 @@ module Api::V1::InboxesHelper
|
||||
rescue StandardError => e
|
||||
raise StandardError, e.message
|
||||
ensure
|
||||
ChatwootExceptionTracker.new(e).capture_exception if e.present?
|
||||
Rails.logger.error "[Api::V1::InboxesHelper] check_imap_connection failed with #{e.message}" if e.present?
|
||||
end
|
||||
|
||||
def check_smtp_connection(channel_data, smtp)
|
||||
|
||||
@@ -37,7 +37,7 @@ module Api::V2::Accounts::ReportsHelper
|
||||
business_hours: ActiveModel::Type::Boolean.new.cast(params[:business_hours])
|
||||
}
|
||||
)
|
||||
).summary
|
||||
).short_summary
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~vue2-datepicker/scss/index';
|
||||
@import 'vue2-datepicker/scss/index';
|
||||
|
||||
.date-picker {
|
||||
&.no-margin {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import 'dashboard/assets/scss/variables';
|
||||
|
||||
.formulate-input {
|
||||
.formulate-input-errors {
|
||||
|
||||
@@ -1,623 +0,0 @@
|
||||
// Foundation for Sites Settings
|
||||
// -----------------------------
|
||||
//
|
||||
// Table of Contents:
|
||||
//
|
||||
// 1. Global
|
||||
// 2. Breakpoints
|
||||
// 3. The Grid
|
||||
// 4. Base Typography
|
||||
// 5. Typography Helpers
|
||||
// 6. Abide
|
||||
// 7. Accordion
|
||||
// 8. Accordion Menu
|
||||
// 9. Badge
|
||||
// 10. Breadcrumbs
|
||||
// 11. Button
|
||||
// 12. Button Group
|
||||
// 13. Callout
|
||||
// 14. Card
|
||||
// 15. Close Button
|
||||
// 16. Drilldown
|
||||
// 17. Dropdown
|
||||
// 18. Dropdown Menu
|
||||
// 19. Forms
|
||||
// 20. Label
|
||||
// 21. Media Object
|
||||
// 22. Menu
|
||||
// 23. Meter
|
||||
// 24. Off-canvas
|
||||
// 25. Orbit
|
||||
// 26. Pagination
|
||||
// 27. Progress Bar
|
||||
// 28. Responsive Embed
|
||||
// 29. Reveal
|
||||
// 30. Slider
|
||||
// 31. Switch
|
||||
// 32. Table
|
||||
// 33. Tabs
|
||||
// 34. Thumbnail
|
||||
// 35. Title Bar
|
||||
// 36. Tooltip
|
||||
// 37. Top Bar
|
||||
|
||||
@import '~foundation-sites/scss/util/util';
|
||||
// 1. Global
|
||||
// ---------
|
||||
|
||||
// Disable contrast warnings in Foundation.
|
||||
$contrast-warnings: false;
|
||||
|
||||
$global-font-size: 16px;
|
||||
$global-width: 100%;
|
||||
$global-lineheight: 1.5;
|
||||
$foundation-palette: (primary: $color-woot,
|
||||
secondary: #5d7592,
|
||||
success: #44ce4b,
|
||||
warning: #ffc532,
|
||||
alert: #ff382d);
|
||||
$light-gray: #c0ccda;
|
||||
$medium-gray: #8492a6;
|
||||
$dark-gray: $color-gray;
|
||||
$black: #000;
|
||||
$white: #fff;
|
||||
$body-background: $white;
|
||||
$body-font-color: $color-body;
|
||||
$body-font-family: 'PlusJakarta',
|
||||
-apple-system,
|
||||
system-ui,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
"Helvetica Neue",
|
||||
Tahoma,
|
||||
Arial,
|
||||
sans-serif;
|
||||
$body-antialiased: true;
|
||||
$global-margin: $space-small;
|
||||
$global-padding: $space-small;
|
||||
$global-weight-normal: normal;
|
||||
$global-weight-bold: bold;
|
||||
$global-radius: 0;
|
||||
$global-text-direction: ltr;
|
||||
$global-flexbox: false;
|
||||
$print-transparent-backgrounds: true;
|
||||
|
||||
@include add-foundation-colors;
|
||||
|
||||
// 2. Breakpoints
|
||||
// --------------
|
||||
|
||||
$breakpoints: (small: 0,
|
||||
medium: 640px,
|
||||
large: 1024px,
|
||||
xlarge: 1200px,
|
||||
xxlarge: 1400px,
|
||||
xxxlarge: 1600px,
|
||||
);
|
||||
$print-breakpoint: large;
|
||||
$breakpoint-classes: (small medium large);
|
||||
|
||||
// 3. The Grid
|
||||
// -----------
|
||||
|
||||
$grid-row-width: $global-width;
|
||||
$grid-column-count: 12;
|
||||
$grid-column-gutter: (small: $zero,
|
||||
medium: $zero);
|
||||
$grid-column-align-edge: true;
|
||||
$block-grid-max: 8;
|
||||
|
||||
// 4. Base Typography
|
||||
// ------------------
|
||||
|
||||
$header-font-family: $body-font-family;
|
||||
$header-font-weight: $font-weight-medium;
|
||||
$header-font-style: normal;
|
||||
$font-family-monospace: $body-font-family;
|
||||
$header-color: $color-heading;
|
||||
$header-lineheight: 1.4;
|
||||
$header-margin-bottom: 0.3125rem;
|
||||
$header-styles: (small: ("h1": ("font-size": 24),
|
||||
"h2": ("font-size": 20),
|
||||
"h3": ("font-size": 19),
|
||||
"h4": ("font-size": 18),
|
||||
"h5": ("font-size": 17),
|
||||
"h6": ("font-size": 16)),
|
||||
medium: ("h1": ("font-size": 48),
|
||||
"h2": ("font-size": 40),
|
||||
"h3": ("font-size": 31),
|
||||
"h4": ("font-size": 25),
|
||||
"h5": ("font-size": 20),
|
||||
"h6": ("font-size": 16)));
|
||||
$header-text-rendering: optimizeLegibility;
|
||||
$small-font-size: 80%;
|
||||
$header-small-font-color: $medium-gray;
|
||||
$paragraph-lineheight: 1.65;
|
||||
$paragraph-margin-bottom: var(--space-small);
|
||||
$paragraph-text-rendering: optimizeLegibility;
|
||||
$code-color: $black;
|
||||
$code-font-family: $font-family-monospace;
|
||||
$code-font-weight: $global-weight-normal;
|
||||
$code-background: $light-gray;
|
||||
$code-border: 1px solid $medium-gray;
|
||||
$code-padding: rem-calc(2 5 1);
|
||||
$anchor-color: $primary-color;
|
||||
$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
|
||||
$anchor-text-decoration: none;
|
||||
$anchor-text-decoration-hover: none;
|
||||
$hr-width: $global-width;
|
||||
$hr-border: 1px solid $medium-gray;
|
||||
$hr-margin: rem-calc(20) auto;
|
||||
$list-lineheight: $paragraph-lineheight;
|
||||
$list-margin-bottom: $paragraph-margin-bottom;
|
||||
$list-style-type: disc;
|
||||
$list-style-position: outside;
|
||||
$list-side-margin: 0.78125rem;
|
||||
$list-nested-side-margin: 0.78125rem;
|
||||
$defnlist-margin-bottom: 0.6875rem;
|
||||
$defnlist-term-weight: $global-weight-bold;
|
||||
$defnlist-term-margin-bottom: 0.1875rem;
|
||||
$blockquote-color: $dark-gray;
|
||||
$blockquote-padding: rem-calc(9 20 0 19);
|
||||
$blockquote-border: 1px solid $medium-gray;
|
||||
$cite-font-size: rem-calc(13);
|
||||
$cite-color: $dark-gray;
|
||||
$cite-pseudo-content: '\2014 \0020';
|
||||
$keystroke-font: $font-family-monospace;
|
||||
$keystroke-color: $black;
|
||||
$keystroke-background: $light-gray;
|
||||
$keystroke-padding: rem-calc(2 4 0);
|
||||
$keystroke-radius: $global-radius;
|
||||
$abbr-underline: 1px dotted $black;
|
||||
|
||||
// 5. Typography Helpers
|
||||
// ---------------------
|
||||
|
||||
$lead-font-size: $global-font-size * 1.25;
|
||||
$lead-lineheight: 1.6;
|
||||
$subheader-lineheight: 1.4;
|
||||
$subheader-color: $dark-gray;
|
||||
$subheader-font-weight: $global-weight-normal;
|
||||
$subheader-margin-top: 0.125rem;
|
||||
$subheader-margin-bottom: 0.3125rem;
|
||||
$stat-font-size: 1.5625rem;
|
||||
|
||||
// 6. Abide
|
||||
// --------
|
||||
|
||||
$abide-inputs: true;
|
||||
$abide-labels: true;
|
||||
$input-background-invalid: get-color(alert);
|
||||
$form-label-color-invalid: get-color(alert);
|
||||
$input-error-color: get-color(alert);
|
||||
$input-error-font-size: rem-calc(12);
|
||||
$input-error-font-weight: $global-weight-bold;
|
||||
|
||||
// 7. Accordion
|
||||
// ------------
|
||||
|
||||
$accordion-background: $white;
|
||||
$accordion-plusminus: true;
|
||||
$accordion-title-font-size: rem-calc(12);
|
||||
$accordion-item-color: $primary-color;
|
||||
$accordion-item-background-hover: $light-gray;
|
||||
$accordion-item-padding: 0.78125rem 0.625rem;
|
||||
$accordion-content-background: $white;
|
||||
$accordion-content-border: 1px solid $light-gray;
|
||||
$accordion-content-color: $body-font-color;
|
||||
$accordion-content-padding: 0.625rem;
|
||||
|
||||
// 8. Accordion Menu
|
||||
// -----------------
|
||||
|
||||
$accordionmenu-arrows: true;
|
||||
$accordionmenu-arrow-color: $primary-color;
|
||||
$accordionmenu-arrow-size: 6px;
|
||||
|
||||
// 9. Badge
|
||||
// --------
|
||||
|
||||
$badge-background: $primary-color;
|
||||
$badge-color: $white;
|
||||
$badge-color-alt: $black;
|
||||
$badge-palette: $foundation-palette;
|
||||
$badge-padding: var(--space-smaller);
|
||||
$badge-minwidth: 2.1em;
|
||||
$badge-font-size: var(--font-size-nano);
|
||||
|
||||
// 10. Breadcrumbs
|
||||
// ---------------
|
||||
|
||||
$breadcrumbs-margin: 0 0 $global-margin 0;
|
||||
$breadcrumbs-item-font-size: rem-calc(11);
|
||||
$breadcrumbs-item-color: $primary-color;
|
||||
$breadcrumbs-item-color-current: $black;
|
||||
$breadcrumbs-item-color-disabled: $medium-gray;
|
||||
$breadcrumbs-item-margin: 0.46875rem;
|
||||
$breadcrumbs-item-uppercase: true;
|
||||
$breadcrumbs-item-slash: true;
|
||||
|
||||
// 11. Button
|
||||
// ----------
|
||||
|
||||
$button-padding: var(--space-smaller) 1em;
|
||||
$button-margin: 0 0 $global-margin 0;
|
||||
$button-fill: solid;
|
||||
$button-background: $primary-color;
|
||||
$button-background-hover: scale-color($button-background, $lightness: -15%);
|
||||
$button-color: $white;
|
||||
$button-color-alt: $white;
|
||||
$button-radius: var(--border-radius-normal);
|
||||
$button-sizes: (tiny: var(--font-size-micro),
|
||||
small: var(--font-size-mini),
|
||||
default: var(--font-size-small),
|
||||
large: var(--font-size-medium));
|
||||
$button-palette: $foundation-palette;
|
||||
$button-opacity-disabled: 0.4;
|
||||
$button-background-hover-lightness: -20%;
|
||||
$button-hollow-hover-lightness: -50%;
|
||||
$button-transition: background-color 0.25s ease-out,
|
||||
color 0.25s ease-out;
|
||||
|
||||
// 12. Button Group
|
||||
// ----------------
|
||||
|
||||
$buttongroup-margin: 0;
|
||||
$buttongroup-spacing: 0;
|
||||
$buttongroup-child-selector: '.button';
|
||||
$buttongroup-expand-max: 6;
|
||||
$buttongroup-radius-on-each: false;
|
||||
|
||||
// 13. Callout
|
||||
// -----------
|
||||
|
||||
$callout-background: $white;
|
||||
$callout-background-fade: 85%;
|
||||
$callout-border: 1px solid rgba($black, 0.25);
|
||||
$callout-margin: 0 0 0.625rem 0;
|
||||
$callout-padding: 0.625rem;
|
||||
$callout-font-color: $body-font-color;
|
||||
$callout-font-color-alt: $body-background;
|
||||
$callout-radius: $global-radius;
|
||||
$callout-link-tint: 30%;
|
||||
|
||||
// 14. Card
|
||||
// --------
|
||||
|
||||
$card-background: $white;
|
||||
$card-font-color: $body-font-color;
|
||||
$card-divider-background: $light-gray;
|
||||
$card-border: 1px solid var(--color-border);
|
||||
$card-shadow: var(--shadow-small);
|
||||
$card-border-radius: var(--border-radius-normal);
|
||||
$card-padding: var(--space-small);
|
||||
$card-margin: $global-margin;
|
||||
|
||||
// 15. Close Button
|
||||
// ----------------
|
||||
|
||||
$closebutton-position: right top;
|
||||
$closebutton-offset-horizontal: (small: 0.66rem,
|
||||
medium: 1rem);
|
||||
$closebutton-offset-vertical: (small: 0.33em,
|
||||
medium: 0.5rem);
|
||||
$closebutton-size: (small: 1.5em,
|
||||
medium: 2em);
|
||||
$closebutton-lineheight: 1;
|
||||
$closebutton-color: $dark-gray;
|
||||
$closebutton-color-hover: $black;
|
||||
|
||||
// 16. Drilldown
|
||||
// -------------
|
||||
|
||||
$drilldown-transition: transform 0.15s linear;
|
||||
$drilldown-arrows: true;
|
||||
$drilldown-arrow-color: $primary-color;
|
||||
$drilldown-arrow-size: 6px;
|
||||
$drilldown-background: $white;
|
||||
|
||||
// 17. Dropdown
|
||||
// ------------
|
||||
|
||||
$dropdown-padding: 0.625rem;
|
||||
$dropdown-background: $body-background;
|
||||
$dropdown-border: 1px solid $medium-gray;
|
||||
$dropdown-font-size: 0.625rem;
|
||||
$dropdown-width: 300px;
|
||||
$dropdown-radius: $global-radius;
|
||||
$dropdown-sizes: (tiny: 100px,
|
||||
small: 200px,
|
||||
large: 400px);
|
||||
|
||||
// 18. Dropdown Menu
|
||||
// -----------------
|
||||
|
||||
$dropdownmenu-arrows: true;
|
||||
$dropdownmenu-arrow-color: $anchor-color;
|
||||
$dropdownmenu-arrow-size: 6px;
|
||||
$dropdownmenu-min-width: 200px;
|
||||
$dropdownmenu-background: $white;
|
||||
$dropdownmenu-border: 1px solid $medium-gray;
|
||||
|
||||
// 19. Forms
|
||||
// ---------
|
||||
|
||||
$fieldset-border: 1px solid $light-gray;
|
||||
$fieldset-padding: $space-two;
|
||||
$fieldset-margin: $space-one $zero;
|
||||
$legend-padding: rem-calc(0 3);
|
||||
$form-spacing: $space-normal;
|
||||
$helptext-color: $color-body;
|
||||
$helptext-font-size: $font-size-small;
|
||||
$helptext-font-style: italic;
|
||||
$input-prefix-color: $color-body;
|
||||
$input-prefix-background: var(--b-100);
|
||||
$input-prefix-border: 1px solid $color-border;
|
||||
$input-prefix-padding: 0.625rem;
|
||||
$form-label-color: $color-body;
|
||||
$form-label-font-size: rem-calc(14);
|
||||
$form-label-font-weight: $font-weight-medium;
|
||||
$form-label-line-height: 1.8;
|
||||
$select-background: $white;
|
||||
$select-triangle-color: $dark-gray;
|
||||
$select-radius: var(--border-radius-normal);
|
||||
$input-color: $color-body;
|
||||
$input-placeholder-color: $light-gray;
|
||||
$input-font-family: inherit;
|
||||
$input-font-size: $font-size-default;
|
||||
$input-font-weight: $global-weight-normal;
|
||||
$input-background: $white;
|
||||
$input-background-focus: $white;
|
||||
$input-background-disabled: $light-gray;
|
||||
$input-border: 1px solid var(--s-200);
|
||||
$input-border-focus: 1px solid lighten($primary-color, 15%);
|
||||
$input-shadow: 0;
|
||||
$input-shadow-focus: 0;
|
||||
$input-cursor-disabled: not-allowed;
|
||||
$input-transition: border-color 0.25s ease-in-out;
|
||||
$input-number-spinners: true;
|
||||
$input-radius: var(--border-radius-normal);
|
||||
$form-button-radius: var(--border-radius-normal);
|
||||
|
||||
// 20. Label
|
||||
// ---------
|
||||
|
||||
$label-background: $white;
|
||||
$label-color: $black;
|
||||
$label-color-alt: $black;
|
||||
$label-palette: $foundation-palette;
|
||||
$label-font-size: $font-size-mini;
|
||||
$label-padding: $space-smaller $space-small;
|
||||
$label-radius: var(--border-radius-small);
|
||||
|
||||
// 21. Media Object
|
||||
// ----------------
|
||||
|
||||
$mediaobject-margin-bottom: $global-margin;
|
||||
$mediaobject-section-padding: $global-padding;
|
||||
$mediaobject-image-width-stacked: 100%;
|
||||
|
||||
// 22. Menu
|
||||
// --------
|
||||
|
||||
$menu-margin: 0;
|
||||
$menu-margin-nested: $space-medium;
|
||||
$menu-item-padding: $space-slab;
|
||||
$menu-item-color-active: $white;
|
||||
$menu-item-background-active: $color-background;
|
||||
$menu-icon-spacing: 0.15625rem;
|
||||
$menu-item-background-hover: $light-gray;
|
||||
$menu-border: $light-gray;
|
||||
|
||||
// 23. Meter
|
||||
// ---------
|
||||
|
||||
$meter-height: 0.625rem;
|
||||
$meter-radius: $global-radius;
|
||||
$meter-background: $medium-gray;
|
||||
$meter-fill-good: $success-color;
|
||||
$meter-fill-medium: $warning-color;
|
||||
$meter-fill-bad: $alert-color;
|
||||
|
||||
// 24. Off-canvas
|
||||
// --------------
|
||||
|
||||
$offcanvas-sizes: (small: 14.375,
|
||||
medium: 14.375,
|
||||
);
|
||||
$offcanvas-vertical-sizes: (small: 14.375,
|
||||
medium: 14.375,
|
||||
);
|
||||
$offcanvas-background: $light-gray;
|
||||
$offcanvas-shadow: 0 0 10px rgba($black, 0.7);
|
||||
$offcanvas-push-zindex: 1;
|
||||
$offcanvas-overlap-zindex: 10;
|
||||
$offcanvas-reveal-zindex: 1;
|
||||
$offcanvas-transition-length: 0.5s;
|
||||
$offcanvas-transition-timing: ease;
|
||||
$offcanvas-fixed-reveal: true;
|
||||
$offcanvas-exit-background: rgba($white, 0.25);
|
||||
$maincontent-class: 'off-canvas-content';
|
||||
|
||||
// 25. Orbit
|
||||
// ---------
|
||||
|
||||
$orbit-bullet-background: $medium-gray;
|
||||
$orbit-bullet-background-active: $dark-gray;
|
||||
$orbit-bullet-diameter: 0.75rem;
|
||||
$orbit-bullet-margin: 0.0625rem;
|
||||
$orbit-bullet-margin-top: 0.5rem;
|
||||
$orbit-bullet-margin-bottom: 0.5rem;
|
||||
$orbit-caption-background: rgba($black, 0.5);
|
||||
$orbit-caption-padding: 0.625rem;
|
||||
$orbit-control-background-hover: rgba($black, 0.5);
|
||||
$orbit-control-padding: 0.625rem;
|
||||
$orbit-control-zindex: 10;
|
||||
|
||||
// 26. Pagination
|
||||
// --------------
|
||||
|
||||
$pagination-font-size: rem-calc(14);
|
||||
$pagination-margin-bottom: $global-margin;
|
||||
$pagination-item-color: $black;
|
||||
$pagination-item-padding: rem-calc(3 10);
|
||||
$pagination-item-spacing: rem-calc(1);
|
||||
$pagination-radius: $global-radius;
|
||||
$pagination-item-background-hover: $light-gray;
|
||||
$pagination-item-background-current: $primary-color;
|
||||
$pagination-item-color-current: $white;
|
||||
$pagination-item-color-disabled: $medium-gray;
|
||||
$pagination-ellipsis-color: $black;
|
||||
$pagination-mobile-items: false;
|
||||
$pagination-mobile-current-item: false;
|
||||
$pagination-arrows: true;
|
||||
|
||||
// 27. Progress Bar
|
||||
// ----------------
|
||||
|
||||
$progress-height: 0.625rem;
|
||||
$progress-background: $medium-gray;
|
||||
$progress-margin-bottom: $global-margin;
|
||||
$progress-meter-background: $primary-color;
|
||||
$progress-radius: $global-radius;
|
||||
|
||||
// 28. Responsive Embed
|
||||
// --------------------
|
||||
|
||||
$responsive-embed-margin-bottom: rem-calc(16);
|
||||
$responsive-embed-ratios: (default: 4 by 3,
|
||||
widescreen: 16 by 9);
|
||||
|
||||
// 29. Reveal
|
||||
// ----------
|
||||
|
||||
$reveal-background: $white;
|
||||
$reveal-width: 600px;
|
||||
$reveal-max-width: $global-width;
|
||||
$reveal-padding: $global-padding;
|
||||
$reveal-border: 1px solid $medium-gray;
|
||||
$reveal-radius: $global-radius;
|
||||
$reveal-zindex: 1005;
|
||||
$reveal-overlay-background: rgba($black, 0.45);
|
||||
|
||||
// 30. Slider
|
||||
// ----------
|
||||
|
||||
$slider-width-vertical: 0.3125rem;
|
||||
$slider-transition: all 0.2s ease-in-out;
|
||||
$slider-height: 0.3125rem;
|
||||
$slider-background: $light-gray;
|
||||
$slider-fill-background: $medium-gray;
|
||||
$slider-handle-height: 0.875rem;
|
||||
$slider-handle-width: 0.875rem;
|
||||
$slider-handle-background: $primary-color;
|
||||
$slider-opacity-disabled: 0.25;
|
||||
$slider-radius: $global-radius;
|
||||
|
||||
// 31. Switch
|
||||
// ----------
|
||||
|
||||
$switch-background: $light-gray;
|
||||
$switch-background-active: $primary-color;
|
||||
$switch-height: $space-two;
|
||||
$switch-height-tiny: $space-slab;
|
||||
$switch-height-small: $space-normal;
|
||||
$switch-height-large: $space-large;
|
||||
$switch-radius: $space-large;
|
||||
$switch-margin: $global-margin;
|
||||
$switch-paddle-background: $white;
|
||||
$switch-paddle-offset: $space-micro;
|
||||
$switch-paddle-radius: $space-large;
|
||||
$switch-paddle-transition: all 0.15s ease-out;
|
||||
|
||||
// 32. Table
|
||||
// ---------
|
||||
|
||||
$table-background: transparent;
|
||||
$table-color-scale: 5%;
|
||||
$table-border: 1px solid transparent;
|
||||
$table-padding: rem-calc(8 10 10);
|
||||
$table-hover-scale: 2%;
|
||||
$table-row-hover: darken($table-background, $table-hover-scale);
|
||||
$table-row-stripe-hover: darken($table-background,
|
||||
$table-color-scale + $table-hover-scale);
|
||||
$table-is-striped: false;
|
||||
$table-striped-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-stripe: even;
|
||||
$table-head-background: smart-scale($table-background, $table-color-scale / 2);
|
||||
$table-head-row-hover: darken($table-head-background, $table-hover-scale);
|
||||
$table-foot-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-foot-row-hover: darken($table-foot-background, $table-hover-scale);
|
||||
$table-head-font-color: $body-font-color;
|
||||
$table-foot-font-color: $body-font-color;
|
||||
$show-header-for-stacked: false;
|
||||
|
||||
// 33. Tabs
|
||||
// --------
|
||||
|
||||
$tab-margin: 0;
|
||||
|
||||
$tab-background: transparent;
|
||||
$tab-background-active: transparent;
|
||||
$tab-item-font-size: $font-size-small;
|
||||
$tab-item-background-hover: transparent;
|
||||
$tab-item-padding: $space-one $zero;
|
||||
$tab-color: $primary-color;
|
||||
$tab-active-color: $primary-color;
|
||||
$tab-expand-max: 6;
|
||||
$tab-content-background: transparent;
|
||||
$tab-content-border: transparent;
|
||||
$tab-content-color: foreground($tab-background, $primary-color);
|
||||
$tab-content-padding: 0.625rem;
|
||||
|
||||
// 34. Thumbnail
|
||||
// -------------
|
||||
|
||||
$thumbnail-border: solid 4px $white;
|
||||
$thumbnail-margin-bottom: $global-margin;
|
||||
$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
|
||||
$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
|
||||
$thumbnail-transition: box-shadow 200ms ease-out;
|
||||
$thumbnail-radius: $global-radius;
|
||||
|
||||
// 35. Title Bar
|
||||
// -------------
|
||||
|
||||
$titlebar-background: $black;
|
||||
$titlebar-color: $white;
|
||||
$titlebar-padding: 0.3125rem;
|
||||
$titlebar-text-font-weight: bold;
|
||||
$titlebar-icon-color: $white;
|
||||
$titlebar-icon-color-hover: $medium-gray;
|
||||
$titlebar-icon-spacing: 0.15625rem;
|
||||
|
||||
// 36. Tooltip
|
||||
// -----------
|
||||
|
||||
$has-tip-font-weight: $global-weight-bold;
|
||||
$has-tip-border-bottom: dotted 1px $dark-gray;
|
||||
$tooltip-background-color: $black;
|
||||
$tooltip-color: $white;
|
||||
$tooltip-padding: 0.46875rem;
|
||||
$tooltip-font-size: $font-size-mini;
|
||||
$tooltip-pip-width: 0.46875rem;
|
||||
$tooltip-pip-height: $tooltip-pip-width * 0.866;
|
||||
$tooltip-radius: $global-radius;
|
||||
|
||||
// 37. Top Bar
|
||||
// -----------
|
||||
|
||||
$topbar-padding: 0.3125;
|
||||
$topbar-background: $light-gray;
|
||||
$topbar-submenu-background: $topbar-background;
|
||||
$topbar-title-spacing: 0.3125 0.625rem 0.3125 0;
|
||||
$topbar-input-width: 200px;
|
||||
$topbar-unstack-breakpoint: medium;
|
||||
|
||||
|
||||
// Internal variable that contains the flex justifying options
|
||||
$-zf-flex-justify: -zf-flex-justify($global-text-direction);
|
||||
|
||||
$menu-items-padding: $space-one;
|
||||
$xy-grid: false;
|
||||
@@ -2,11 +2,6 @@
|
||||
@apply bg-slate-25 dark:bg-slate-800;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
@include flex-align(center, middle);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bottom-space-fix {
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import '~widget/assets/scss/mixins';
|
||||
@import 'dashboard/assets/scss/variables';
|
||||
@import 'widget/assets/scss/mixins';
|
||||
|
||||
$spinner-before-border-color: rgba(255, 255, 255, 0.7);
|
||||
|
||||
|
||||
@@ -89,9 +89,6 @@ $swift-ease-out-duration: .4s !default;
|
||||
$swift-ease-out-function: cubic-bezier(0.37, 0, 0.63, 1) !default;
|
||||
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-function !default;
|
||||
|
||||
// Ionicons
|
||||
$ionicons-font-path: '~ionicons/fonts';
|
||||
|
||||
// Transitions
|
||||
$transition-ease-in: all 0.250s ease-in;
|
||||
|
||||
|
||||
@@ -15,36 +15,13 @@
|
||||
@import 'variables';
|
||||
|
||||
@import 'mixins';
|
||||
@import 'foundation-settings';
|
||||
@import 'helper-classes';
|
||||
@import 'formulate';
|
||||
@import 'date-picker';
|
||||
|
||||
@import 'foundation-sites/scss/foundation';
|
||||
|
||||
@include foundation-everything($flex: true);
|
||||
|
||||
@include foundation-prototype-text-utilities;
|
||||
@include foundation-prototype-text-transformation;
|
||||
@include foundation-prototype-text-decoration;
|
||||
@include foundation-prototype-font-styling;
|
||||
@include foundation-prototype-list-style-type;
|
||||
@include foundation-prototype-rounded;
|
||||
@include foundation-prototype-bordered;
|
||||
@include foundation-prototype-shadow;
|
||||
@include foundation-prototype-separator;
|
||||
@include foundation-prototype-overflow;
|
||||
@include foundation-prototype-display;
|
||||
@include foundation-prototype-position;
|
||||
@include foundation-prototype-border-box;
|
||||
@include foundation-prototype-border-none;
|
||||
@include foundation-prototype-sizing;
|
||||
@include foundation-prototype-spacing;
|
||||
|
||||
@import 'typography';
|
||||
@import 'layout';
|
||||
@import 'animations';
|
||||
@import 'foundation-custom';
|
||||
@import 'rtl';
|
||||
|
||||
@import 'widgets/buttons';
|
||||
@@ -52,15 +29,11 @@
|
||||
@import 'widgets/conversation-card';
|
||||
@import 'widgets/conversation-view';
|
||||
@import 'widgets/forms';
|
||||
@import 'widgets/login';
|
||||
@import 'widgets/modal';
|
||||
@import 'widgets/reply-box';
|
||||
@import 'widgets/report';
|
||||
@import 'widgets/search-box';
|
||||
@import 'widgets/sidemenu';
|
||||
@import 'widgets/snackbar';
|
||||
@import 'widgets/states';
|
||||
@import 'widgets/status-bar';
|
||||
@import 'widgets/tabs';
|
||||
@import 'widgets/woot-tables';
|
||||
|
||||
@@ -69,7 +42,6 @@
|
||||
|
||||
@import 'plugins/multiselect';
|
||||
@import 'plugins/dropdown';
|
||||
@import '~shared/assets/stylesheets/ionicons';
|
||||
@import 'utility-helpers';
|
||||
|
||||
.tooltip {
|
||||
|
||||
@@ -10,21 +10,14 @@
|
||||
@import 'variables';
|
||||
|
||||
@import 'vue-multiselect/dist/vue-multiselect.min.css';
|
||||
@import '~shared/assets/stylesheets/ionicons';
|
||||
|
||||
@import 'mixins';
|
||||
@import 'foundation-settings';
|
||||
@import 'helper-classes';
|
||||
@import 'foundation-sites/scss/foundation';
|
||||
|
||||
@include foundation-prototype-spacing;
|
||||
@include foundation-everything($flex: true);
|
||||
|
||||
@import 'typography';
|
||||
@import 'layout';
|
||||
@import 'animations';
|
||||
|
||||
@import 'foundation-custom';
|
||||
@import 'widgets/buttons';
|
||||
@import 'widgets/forms';
|
||||
|
||||
|
||||
@@ -76,7 +76,11 @@
|
||||
|
||||
&.left {
|
||||
.bubble {
|
||||
@apply border border-slate-50 dark:border-slate-700 bg-white dark:bg-slate-700 text-black-900 dark:text-slate-50 rounded-r-lg rounded-l mr-auto break-words;
|
||||
@apply rounded-r-lg rounded-l mr-auto break-words;
|
||||
|
||||
&:not(.is-unsupported) {
|
||||
@apply border border-slate-50 dark:border-slate-700 bg-white dark:bg-slate-700 text-black-900 dark:text-slate-50
|
||||
}
|
||||
|
||||
&.is-image {
|
||||
@apply rounded-lg;
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
.auth-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Outside login wrapper
|
||||
.login {
|
||||
@include full-height;
|
||||
overflow-y: auto;
|
||||
padding-top: $space-larger * 1.2;
|
||||
|
||||
.login__hero {
|
||||
margin-bottom: $space-larger;
|
||||
|
||||
.hero__logo {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.hero__title {
|
||||
font-weight: $font-weight-light;
|
||||
margin-top: $space-larger;
|
||||
}
|
||||
|
||||
.hero__sub {
|
||||
color: $medium-gray;
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
}
|
||||
|
||||
// Login box
|
||||
.login-box {
|
||||
@include background-white;
|
||||
@include border-normal;
|
||||
@include elegant-card;
|
||||
|
||||
border-radius: $space-smaller;
|
||||
padding: $space-large;
|
||||
|
||||
label {
|
||||
color: $color-gray;
|
||||
font-size: $font-size-default;
|
||||
|
||||
input {
|
||||
font-size: $font-size-default;
|
||||
height: $space-larger;
|
||||
padding: $space-slab;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
height: $space-larger;
|
||||
}
|
||||
}
|
||||
|
||||
.sigin__footer {
|
||||
font-size: $font-size-default;
|
||||
padding: $space-medium;
|
||||
|
||||
> a {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
.modal-mask {
|
||||
// @include flex;
|
||||
// @include flex-align(center, middle);
|
||||
@apply flex items-center justify-center bg-modal dark:bg-modal z-[9990] h-full left-0 fixed top-0 w-full;
|
||||
@apply flex items-center justify-center bg-modal-backdrop-light dark:bg-modal-backdrop-dark z-[9990] h-full left-0 fixed top-0 w-full;
|
||||
}
|
||||
|
||||
.page-top-bar {
|
||||
@@ -45,8 +43,6 @@
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
// @include flex;
|
||||
// @include flex-align($x: flex-end, $y: middle);
|
||||
@apply flex justify-end items-center py-2 px-0 gap-2;
|
||||
|
||||
&.justify-content-end {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
.reply-box__top {
|
||||
.icon {
|
||||
color: $medium-gray;
|
||||
color: var(--slate-500);
|
||||
cursor: pointer;
|
||||
font-size: $font-size-medium;
|
||||
margin-right: $space-small;
|
||||
@@ -34,7 +34,7 @@
|
||||
resize: none;
|
||||
}
|
||||
|
||||
> textarea {
|
||||
>textarea {
|
||||
@include ghost-input();
|
||||
background: transparent;
|
||||
margin: 0;
|
||||
@@ -52,7 +52,7 @@
|
||||
.reply-box__top {
|
||||
@apply bg-yellow-100 dark:bg-yellow-800;
|
||||
|
||||
> input {
|
||||
>input {
|
||||
@apply bg-yellow-100 dark:bg-yellow-800;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,10 @@
|
||||
.side-menu {
|
||||
i {
|
||||
margin-right: var(--space-smaller);
|
||||
min-width: var(--space-two);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
z-index: 1024 - 1;
|
||||
|
||||
//logo
|
||||
.logo {
|
||||
img {
|
||||
max-height: 108px;
|
||||
padding: $woot-logo-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.nested {
|
||||
a {
|
||||
font-size: var(--font-size-small);
|
||||
margin-bottom: var(--space-micro);
|
||||
margin-top: var(--space-micro);
|
||||
|
||||
.inbox-icon {
|
||||
display: inline-block;
|
||||
margin-right: var(--space-micro);
|
||||
min-width: var(--space-normal);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bottom-nav
|
||||
.bottom-nav {
|
||||
@include flex;
|
||||
@include space-between-column;
|
||||
@include border-normal-top;
|
||||
flex-direction: column;
|
||||
padding: var(--space-one) var(--space-normal) var(--space-one)
|
||||
var(--space-one);
|
||||
padding: var(--space-one) var(--space-normal) var(--space-one) var(--space-one);
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -519,6 +519,9 @@ export default {
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
teamId() {
|
||||
this.updateVirtualListProps('teamId', this.teamId);
|
||||
},
|
||||
activeTeam() {
|
||||
this.resetAndFetchData();
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<span
|
||||
class="attribute-name"
|
||||
:class="{ error: $v.editedValue.$error }"
|
||||
:class="{ error: v$.editedValue.$error }"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
@@ -39,8 +39,8 @@
|
||||
:type="inputType"
|
||||
class="input-group-field"
|
||||
autofocus="true"
|
||||
:class="{ error: $v.editedValue.$error }"
|
||||
@blur="$v.editedValue.$touch"
|
||||
:class="{ error: v$.editedValue.$error }"
|
||||
@blur="v$.editedValue.$touch"
|
||||
@keyup.enter="onUpdate"
|
||||
/>
|
||||
<div class="input-group-button">
|
||||
@@ -122,25 +122,37 @@
|
||||
|
||||
<script>
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { required, url } from 'vuelidate/lib/validators';
|
||||
import { required, url } from '@vuelidate/validators';
|
||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
||||
import { isValidURL } from '../helper/URLHelper';
|
||||
import customAttributeMixin from '../mixins/customAttributeMixin';
|
||||
const DATE_FORMAT = 'yyyy-MM-dd';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiselectDropdown,
|
||||
},
|
||||
mixins: [customAttributeMixin],
|
||||
props: {
|
||||
label: { type: String, required: true },
|
||||
values: { type: Array, default: () => [] },
|
||||
value: { type: [String, Number, Boolean], default: '' },
|
||||
showActions: { type: Boolean, default: false },
|
||||
attributeType: { type: String, default: 'text' },
|
||||
attributeRegex: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
regexCue: { type: String, default: null },
|
||||
regexEnabled: { type: Boolean, default: false },
|
||||
attributeKey: { type: String, required: true },
|
||||
contactId: { type: Number, default: null },
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: false,
|
||||
@@ -198,12 +210,17 @@ export default {
|
||||
return this.isAttributeTypeLink ? 'url' : this.attributeType;
|
||||
},
|
||||
shouldShowErrorMessage() {
|
||||
return this.$v.editedValue.$error;
|
||||
return this.v$.editedValue.$error;
|
||||
},
|
||||
errorMessage() {
|
||||
if (this.$v.editedValue.url) {
|
||||
if (this.v$.editedValue.url) {
|
||||
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_URL');
|
||||
}
|
||||
if (!this.v$.editedValue.regexValidation) {
|
||||
return this.regexCue
|
||||
? this.regexCue
|
||||
: this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_INPUT');
|
||||
}
|
||||
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.REQUIRED');
|
||||
},
|
||||
},
|
||||
@@ -221,7 +238,15 @@ export default {
|
||||
};
|
||||
}
|
||||
return {
|
||||
editedValue: { required },
|
||||
editedValue: {
|
||||
required,
|
||||
regexValidation: value => {
|
||||
return !(
|
||||
this.attributeRegex &&
|
||||
!this.getRegexp(this.attributeRegex).test(value)
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -259,8 +284,8 @@ export default {
|
||||
this.attributeType === 'date'
|
||||
? parseISO(this.editedValue)
|
||||
: this.editedValue;
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
this.v$.$touch();
|
||||
if (this.v$.$invalid) {
|
||||
return;
|
||||
}
|
||||
this.isEditing = false;
|
||||
@@ -281,11 +306,14 @@ export default {
|
||||
.checkbox-wrap {
|
||||
@apply flex items-center;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
@apply my-0 mr-2 ml-0;
|
||||
}
|
||||
|
||||
.attribute-name {
|
||||
@apply w-full text-slate-800 dark:text-slate-100;
|
||||
|
||||
&.error {
|
||||
@apply text-red-400 dark:text-red-500;
|
||||
}
|
||||
@@ -302,6 +330,7 @@ export default {
|
||||
.value {
|
||||
@apply bg-slate-50 dark:bg-slate-700 mb-0;
|
||||
}
|
||||
|
||||
.edit-button {
|
||||
@apply block;
|
||||
}
|
||||
@@ -311,10 +340,12 @@ export default {
|
||||
::v-deep {
|
||||
.selector-wrap {
|
||||
@apply m-0 top-1;
|
||||
|
||||
.selector-name {
|
||||
@apply ml-0;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
@apply ml-0;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
<template>
|
||||
<transition name="network-notification-fade" tag="div">
|
||||
<div v-show="showNotification" class="ui-notification-container">
|
||||
<div class="ui-notification">
|
||||
<fluent-icon icon="wifi-off" />
|
||||
<p class="ui-notification-text">
|
||||
{{
|
||||
useInstallationName(
|
||||
$t('NETWORK.NOTIFICATION.TEXT'),
|
||||
globalConfig.installationName
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<woot-button variant="clear" size="small" @click="refreshPage">
|
||||
{{ $t('NETWORK.BUTTON.REFRESH') }}
|
||||
</woot-button>
|
||||
<div v-show="showNotification" class="fixed top-4 left-2 z-50 group">
|
||||
<div
|
||||
class="flex items-center justify-between py-1 px-2 w-full rounded-lg shadow-lg bg-yellow-200 dark:bg-yellow-700 relative"
|
||||
>
|
||||
<fluent-icon
|
||||
icon="wifi-off"
|
||||
class="text-yellow-700/50 dark:text-yellow-50"
|
||||
size="18"
|
||||
/>
|
||||
<span
|
||||
class="text-xs tracking-wide font-medium px-2 text-yellow-700/70 dark:text-yellow-50"
|
||||
>
|
||||
{{ $t('NETWORK.NOTIFICATION.OFFLINE') }}
|
||||
</span>
|
||||
<woot-button
|
||||
variant="smooth"
|
||||
:title="$t('NETWORK.BUTTON.REFRESH')"
|
||||
variant="clear"
|
||||
size="small"
|
||||
color-scheme="warning"
|
||||
icon="dismiss-circle"
|
||||
icon="arrow-clockwise"
|
||||
class="visible transition-all duration-500 ease-in-out ml-1"
|
||||
@click="refreshPage"
|
||||
/>
|
||||
<woot-button
|
||||
variant="clear"
|
||||
size="small"
|
||||
color-scheme="warning"
|
||||
icon="dismiss"
|
||||
@click="closeNotification"
|
||||
/>
|
||||
</div>
|
||||
@@ -47,7 +56,12 @@ export default {
|
||||
mounted() {
|
||||
window.addEventListener('offline', this.updateOnlineStatus);
|
||||
window.bus.$on(BUS_EVENTS.WEBSOCKET_DISCONNECT, () => {
|
||||
this.updateOnlineStatus({ type: 'offline' });
|
||||
// TODO: Remove this after completing the conversation list refetching
|
||||
// TODO: DIRTY FIX : CLEAN UP THIS WITH PROPER FIX, DELAYING THE RECONNECT FOR NOW
|
||||
// THE CABLE IS FIRING IS VERY COMMON AND THUS INTERFERING USER EXPERIENCE
|
||||
setTimeout(() => {
|
||||
this.updateOnlineStatus({ type: 'offline' });
|
||||
}, 4000);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -72,33 +86,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.ui-notification-container {
|
||||
max-width: 25rem;
|
||||
position: absolute;
|
||||
right: var(--space-normal);
|
||||
top: var(--space-normal);
|
||||
z-index: var(--z-index-very-high);
|
||||
}
|
||||
|
||||
.ui-notification {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
background-color: var(--y-100);
|
||||
border-radius: var(--border-radius-medium);
|
||||
box-shadow: var(--shadow-large);
|
||||
|
||||
min-width: 15rem;
|
||||
padding: var(--space-normal);
|
||||
}
|
||||
|
||||
.ui-notification-text {
|
||||
margin: 0 var(--space-small);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/* eslint no-plusplus: 0 */
|
||||
import AvatarUploader from './widgets/forms/AvatarUploader.vue';
|
||||
import Bar from './widgets/chart/BarChart';
|
||||
import Button from './ui/WootButton';
|
||||
import Code from './Code';
|
||||
import ColorPicker from './widgets/ColorPicker';
|
||||
import Button from './ui/WootButton.vue';
|
||||
import Code from './Code.vue';
|
||||
import ColorPicker from './widgets/ColorPicker.vue';
|
||||
import ConfirmDeleteModal from './widgets/modal/ConfirmDeleteModal.vue';
|
||||
import ConfirmModal from './widgets/modal/ConfirmationModal.vue';
|
||||
import ContextMenu from './ui/ContextMenu.vue';
|
||||
import DeleteModal from './widgets/modal/DeleteModal.vue';
|
||||
import DropdownItem from 'shared/components/ui/dropdown/DropdownItem';
|
||||
import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu';
|
||||
import FeatureToggle from './widgets/FeatureToggle';
|
||||
import DropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||
import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||
import FeatureToggle from './widgets/FeatureToggle.vue';
|
||||
import HorizontalBar from './widgets/chart/HorizontalBarChart';
|
||||
import Input from './widgets/forms/Input.vue';
|
||||
import PhoneInput from './widgets/forms/PhoneInput.vue';
|
||||
import Label from './ui/Label';
|
||||
import LoadingState from './widgets/LoadingState';
|
||||
import Modal from './Modal';
|
||||
import ModalHeader from './ModalHeader';
|
||||
import ReportStatsCard from './widgets/ReportStatsCard';
|
||||
import SidemenuIcon from './SidemenuIcon';
|
||||
import Spinner from 'shared/components/Spinner';
|
||||
import SubmitButton from './buttons/FormSubmitButton';
|
||||
import Label from './ui/Label.vue';
|
||||
import LoadingState from './widgets/LoadingState.vue';
|
||||
import Modal from './Modal.vue';
|
||||
import ModalHeader from './ModalHeader.vue';
|
||||
import ReportStatsCard from './widgets/ReportStatsCard.vue';
|
||||
import SidemenuIcon from './SidemenuIcon.vue';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import SubmitButton from './buttons/FormSubmitButton.vue';
|
||||
import Tabs from './ui/Tabs/Tabs';
|
||||
import TabsItem from './ui/Tabs/TabsItem';
|
||||
import TabsItem from './ui/Tabs/TabsItem.vue';
|
||||
import Thumbnail from './widgets/Thumbnail.vue';
|
||||
|
||||
const WootUIKit = {
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
<form class="flex flex-col w-full" @submit.prevent="addAccount">
|
||||
<div class="w-full">
|
||||
<label :class="{ error: $v.accountName.$error }">
|
||||
<label :class="{ error: v$.accountName.$error }">
|
||||
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
||||
<input
|
||||
v-model.trim="accountName"
|
||||
type="text"
|
||||
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
||||
@input="$v.accountName.$touch"
|
||||
@input="v$.accountName.$touch"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
@@ -33,8 +33,8 @@
|
||||
<div class="w-full">
|
||||
<woot-submit-button
|
||||
:disabled="
|
||||
$v.accountName.$invalid ||
|
||||
$v.accountName.$invalid ||
|
||||
v$.accountName.$invalid ||
|
||||
v$.accountName.$invalid ||
|
||||
uiFlags.isCreating
|
||||
"
|
||||
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
||||
@@ -49,9 +49,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required, minLength } from 'vuelidate/lib/validators';
|
||||
import { required, minLength } from '@vuelidate/validators';
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
@@ -65,6 +66,9 @@ export default {
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
accountName: '',
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@
|
||||
class="bg-slate-50 dark:bg-slate-700 rounded text-xxs font-medium mx-1 py-0 px-1"
|
||||
:class="
|
||||
isCountZero
|
||||
? `text-slate-300 dark:text-slate-700`
|
||||
? `text-slate-300 dark:text-slate-500`
|
||||
: `text-slate-700 dark:text-slate-50`
|
||||
"
|
||||
>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export default {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'WootTabs',
|
||||
props: {
|
||||
index: {
|
||||
@@ -73,19 +75,25 @@ export default {
|
||||
});
|
||||
const leftButton = this.createScrollButton(createElement, 'left');
|
||||
const rightButton = this.createScrollButton(createElement, 'right');
|
||||
return (
|
||||
<div
|
||||
class={{
|
||||
return createElement(
|
||||
'div',
|
||||
{
|
||||
class: {
|
||||
'tabs--container--with-border': this.border,
|
||||
'tabs--container': true,
|
||||
}}
|
||||
>
|
||||
{leftButton}
|
||||
<ul class={{ tabs: true, 'tabs--with-scroll': this.hasScroll }}>
|
||||
{Tabs}
|
||||
</ul>
|
||||
{rightButton}
|
||||
</div>
|
||||
},
|
||||
},
|
||||
[
|
||||
leftButton,
|
||||
createElement(
|
||||
'ul',
|
||||
{
|
||||
class: { tabs: true, 'tabs--with-scroll': this.hasScroll },
|
||||
},
|
||||
Tabs
|
||||
),
|
||||
rightButton,
|
||||
]
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
<woot-input
|
||||
v-model="value"
|
||||
type="text"
|
||||
:class="{ error: $v.value.$error }"
|
||||
:class="{ error: v$.value.$error }"
|
||||
:placeholder="
|
||||
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.KEY_PLACEHOLDER')
|
||||
"
|
||||
@blur="$v.value.$touch"
|
||||
@blur="v$.value.$touch"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between gap-2 py-2 px-0 w-full">
|
||||
@@ -27,7 +27,7 @@
|
||||
<woot-button variant="clear" @click.prevent="onDismiss">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }}
|
||||
</woot-button>
|
||||
<woot-button :is-disabled="$v.value.$invalid">
|
||||
<woot-button :is-disabled="v$.value.$invalid">
|
||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
@@ -37,15 +37,19 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import { mapGetters } from 'vuex';
|
||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
mixins: [aiMixin, alertMixin, uiSettingsMixin],
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
|
||||
@@ -53,8 +53,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
@import 'dashboard/assets/scss/variables';
|
||||
@import 'dashboard/assets/scss/mixins';
|
||||
|
||||
.colorpicker {
|
||||
position: relative;
|
||||
|
||||
@@ -84,7 +84,10 @@ import {
|
||||
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings';
|
||||
import { replaceVariablesInMessage } from '@chatwoot/utils';
|
||||
import {
|
||||
replaceVariablesInMessage,
|
||||
createTypingIndicator,
|
||||
} from '@chatwoot/utils';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
|
||||
import { uploadFile } from 'dashboard/helper/uploadHelper';
|
||||
@@ -140,6 +143,15 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typingIndicator: createTypingIndicator(
|
||||
() => {
|
||||
this.$emit('typing-on');
|
||||
},
|
||||
() => {
|
||||
this.$emit('typing-off');
|
||||
},
|
||||
TYPING_INDICATOR_IDLE_TIME
|
||||
),
|
||||
showUserMentions: false,
|
||||
showCannedMenu: false,
|
||||
showVariables: false,
|
||||
@@ -638,15 +650,6 @@ export default {
|
||||
hideMentions() {
|
||||
this.showUserMentions = false;
|
||||
},
|
||||
resetTyping() {
|
||||
this.$emit('typing-off');
|
||||
this.idleTimer = null;
|
||||
},
|
||||
turnOffIdleTimer() {
|
||||
if (this.idleTimer) {
|
||||
clearTimeout(this.idleTimer);
|
||||
}
|
||||
},
|
||||
handleLineBreakWhenEnterToSendEnabled(event) {
|
||||
if (
|
||||
hasPressedEnterAndNotCmdOrShift(event) &&
|
||||
@@ -666,14 +669,7 @@ export default {
|
||||
}
|
||||
},
|
||||
onKeyup() {
|
||||
if (!this.idleTimer) {
|
||||
this.$emit('typing-on');
|
||||
}
|
||||
this.turnOffIdleTimer();
|
||||
this.idleTimer = setTimeout(
|
||||
() => this.resetTyping(),
|
||||
TYPING_INDICATOR_IDLE_TIME
|
||||
);
|
||||
this.typingIndicator.start();
|
||||
this.updateImgToolbarOnDelete();
|
||||
},
|
||||
onKeydown(event) {
|
||||
@@ -685,8 +681,7 @@ export default {
|
||||
}
|
||||
},
|
||||
onBlur() {
|
||||
this.turnOffIdleTimer();
|
||||
this.resetTyping();
|
||||
this.typingIndicator.stop();
|
||||
this.$emit('blur');
|
||||
},
|
||||
onFocus() {
|
||||
@@ -710,10 +705,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@chatwoot/prosemirror-schema/src/styles/base.scss';
|
||||
@import '@chatwoot/prosemirror-schema/src/styles/base.scss';
|
||||
|
||||
.ProseMirror-menubar-wrapper {
|
||||
@apply flex flex-col;
|
||||
|
||||
.ProseMirror-menubar {
|
||||
min-height: var(--space-two) !important;
|
||||
@apply -ml-2.5 pb-0 bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-100;
|
||||
@@ -722,6 +718,7 @@ export default {
|
||||
@apply bg-slate-75 dark:bg-slate-800;
|
||||
}
|
||||
}
|
||||
|
||||
> .ProseMirror {
|
||||
@apply p-0 break-words text-slate-800 dark:text-slate-100;
|
||||
|
||||
|
||||
@@ -101,10 +101,10 @@
|
||||
<transition name="modal-fade">
|
||||
<div
|
||||
v-show="$refs.upload && $refs.upload.dropActive"
|
||||
class="fixed top-0 bottom-0 left-0 right-0 z-20 flex flex-col items-center justify-center w-full h-full gap-2 text-slate-600 dark:text-slate-200 bg-white_transparent dark:bg-black_transparent"
|
||||
class="fixed top-0 bottom-0 left-0 right-0 z-20 flex flex-col items-center justify-center w-full h-full gap-2 text-slate-900 dark:text-slate-50 bg-modal-backdrop-light dark:bg-modal-backdrop-dark"
|
||||
>
|
||||
<fluent-icon icon="cloud-backup" size="40" />
|
||||
<h4 class="page-sub-title text-slate-600 dark:text-slate-200">
|
||||
<h4 class="page-sub-title text-slate-900 dark:text-slate-50">
|
||||
{{ $t('CONVERSATION.REPLYBOX.DRAG_DROP') }}
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<mention-box :items="items" @mention-select="handleMentionClick">
|
||||
<mention-box
|
||||
v-if="items.length"
|
||||
:items="items"
|
||||
@mention-select="handleMentionClick"
|
||||
>
|
||||
<template slot-scope="{ item }">
|
||||
<strong>{{ item.label }}</strong> - {{ item.description }}
|
||||
</template>
|
||||
|
||||
+8
-4
@@ -41,7 +41,7 @@
|
||||
:show-query-operator="i !== appliedFilters.length - 1"
|
||||
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
||||
:grouped-filters="true"
|
||||
:v="$v.appliedFilters.$each[i]"
|
||||
:v="v$.appliedFilters.$each[i]"
|
||||
@resetFilter="resetFilter(i, appliedFilters[i])"
|
||||
@removeFilter="removeFilter(i)"
|
||||
/>
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
<script>
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
||||
import { required, requiredIf } from '@vuelidate/validators';
|
||||
import FilterInputBox from '../FilterInput/Index.vue';
|
||||
import languages from './advancedFilterItems/languages';
|
||||
import countries from 'shared/constants/countries.js';
|
||||
@@ -89,6 +89,7 @@ import { filterAttributeGroups } from './advancedFilterItems';
|
||||
import filterMixin from 'shared/mixins/filterMixin';
|
||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -117,6 +118,9 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
validations: {
|
||||
appliedFilters: {
|
||||
required,
|
||||
@@ -347,8 +351,8 @@ export default {
|
||||
}
|
||||
},
|
||||
submitFilterQuery() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) return;
|
||||
this.v$.$touch();
|
||||
if (this.v$.$invalid) return;
|
||||
this.$store.dispatch(
|
||||
'setConversationFilters',
|
||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||
|
||||
@@ -45,14 +45,14 @@
|
||||
}}</label>
|
||||
</div>
|
||||
<div v-if="sentToOtherEmailAddress" class="w-[50%] mt-1">
|
||||
<label :class="{ error: $v.email.$error }">
|
||||
<label :class="{ error: v$.email.$error }">
|
||||
<input
|
||||
v-model.trim="email"
|
||||
type="text"
|
||||
:placeholder="$t('EMAIL_TRANSCRIPT.FORM.EMAIL.PLACEHOLDER')"
|
||||
@input="$v.email.$touch"
|
||||
@input="v$.email.$touch"
|
||||
/>
|
||||
<span v-if="$v.email.$error" class="message">
|
||||
<span v-if="v$.email.$error" class="message">
|
||||
{{ $t('EMAIL_TRANSCRIPT.FORM.EMAIL.ERROR') }}
|
||||
</span>
|
||||
</label>
|
||||
@@ -73,8 +73,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||
import { required, minLength, email } from '@vuelidate/validators';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
@@ -87,6 +89,9 @@ export default {
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
email: '',
|
||||
@@ -108,7 +113,7 @@ export default {
|
||||
isFormValid() {
|
||||
if (this.selectedType) {
|
||||
if (this.sentToOtherEmailAddress) {
|
||||
return !!this.email && !this.$v.email.$error;
|
||||
return !!this.email && !this.v$.email.$error;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<template>
|
||||
<li v-if="shouldRenderMessage" :id="`message${data.id}`" :class="alignBubble">
|
||||
<div :class="wrapClass">
|
||||
<div v-if="isFailed && !hasOneDayPassed" class="message-failed--alert">
|
||||
<div
|
||||
v-if="isFailed && !hasOneDayPassed && !isAnEmailInbox"
|
||||
class="message-failed--alert"
|
||||
>
|
||||
<woot-button
|
||||
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
|
||||
size="tiny"
|
||||
@@ -29,8 +32,19 @@
|
||||
:message-type="data.message_type"
|
||||
:parent-has-attachments="hasAttachments"
|
||||
/>
|
||||
<div v-if="isUnsupported">
|
||||
<template v-if="isAFacebookInbox && isInstagram">
|
||||
{{ $t('CONVERSATION.UNSUPPORTED_MESSAGE_INSTAGRAM') }}
|
||||
</template>
|
||||
<template v-else-if="isAFacebookInbox">
|
||||
{{ $t('CONVERSATION.UNSUPPORTED_MESSAGE_FACEBOOK') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $t('CONVERSATION.UNSUPPORTED_MESSAGE') }}
|
||||
</template>
|
||||
</div>
|
||||
<bubble-text
|
||||
v-if="data.content"
|
||||
v-else-if="data.content"
|
||||
:message="message"
|
||||
:is-email="isEmailContentType"
|
||||
:display-quoted-button="displayQuotedButton"
|
||||
@@ -176,6 +190,14 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isAFacebookInbox: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isInstagram: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isAWhatsAppChannel: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -184,6 +206,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isAnEmailInbox: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
inboxSupportsReplyTo: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
@@ -219,6 +245,7 @@ export default {
|
||||
this.hasAttachments ||
|
||||
this.data.content ||
|
||||
this.isEmailContentType ||
|
||||
this.isUnsupported ||
|
||||
this.isAnIntegrationMessage
|
||||
);
|
||||
},
|
||||
@@ -407,6 +434,7 @@ export default {
|
||||
return {
|
||||
bubble: this.isBubble,
|
||||
'is-private': this.data.private,
|
||||
'is-unsupported': this.isUnsupported,
|
||||
'is-image': this.hasMediaAttachment('image'),
|
||||
'is-video': this.hasMediaAttachment('video'),
|
||||
'is-text': this.hasText,
|
||||
@@ -415,6 +443,9 @@ export default {
|
||||
'is-email': this.isEmailContentType,
|
||||
};
|
||||
},
|
||||
isUnsupported() {
|
||||
return this.contentAttributes.is_unsupported ?? false;
|
||||
},
|
||||
isPending() {
|
||||
return this.data.status === MESSAGE_STATUS.PROGRESS;
|
||||
},
|
||||
@@ -426,11 +457,7 @@ export default {
|
||||
return !this.sender.type || this.sender.type === 'agent_bot';
|
||||
},
|
||||
shouldShowContextMenu() {
|
||||
return !(this.isFailed || this.isPending);
|
||||
},
|
||||
errorMessage() {
|
||||
const { meta } = this.data;
|
||||
return meta ? meta.error : '';
|
||||
return !(this.isFailed || this.isPending || this.isUnsupported);
|
||||
},
|
||||
showAvatar() {
|
||||
if (this.isOutgoing || this.isTemplate) {
|
||||
@@ -532,6 +559,14 @@ export default {
|
||||
> .bubble {
|
||||
@apply min-w-[128px];
|
||||
|
||||
&.is-unsupported {
|
||||
@apply text-xs max-w-[300px] border-dashed border border-slate-200 text-slate-600 dark:text-slate-200 bg-slate-50 dark:bg-slate-700 dark:border-slate-500;
|
||||
|
||||
.message-text--metadata .time {
|
||||
@apply text-slate-400 dark:text-slate-300;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-image,
|
||||
&.is-video {
|
||||
@apply p-0 overflow-hidden;
|
||||
@@ -544,10 +579,12 @@ export default {
|
||||
> video {
|
||||
@apply rounded-lg;
|
||||
}
|
||||
|
||||
> video {
|
||||
@apply h-full w-full object-cover;
|
||||
}
|
||||
}
|
||||
|
||||
.video {
|
||||
@apply h-[11.25rem];
|
||||
}
|
||||
@@ -562,9 +599,11 @@ export default {
|
||||
.file--icon {
|
||||
@apply text-woot-400 dark:text-woot-400;
|
||||
}
|
||||
|
||||
.text-block-title {
|
||||
@apply text-slate-700 dark:text-slate-700;
|
||||
}
|
||||
|
||||
.download.button {
|
||||
@apply text-woot-400 dark:text-woot-400;
|
||||
}
|
||||
@@ -573,6 +612,7 @@ export default {
|
||||
&.is-private.is-text > .message-text__wrap .link {
|
||||
@apply text-woot-600 dark:text-woot-200;
|
||||
}
|
||||
|
||||
&.is-private.is-text > .message-text__wrap .prosemirror-mention-node {
|
||||
@apply font-bold bg-none rounded-sm p-0 bg-yellow-100 dark:bg-yellow-700 text-slate-700 dark:text-slate-25 underline;
|
||||
}
|
||||
@@ -583,6 +623,7 @@ export default {
|
||||
.message-text--metadata .time {
|
||||
@apply text-violet-50 dark:text-violet-50;
|
||||
}
|
||||
|
||||
&.is-private .message-text--metadata .time {
|
||||
@apply text-slate-400 dark:text-slate-400;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
:is-a-tweet="isATweet"
|
||||
:is-a-whatsapp-channel="isAWhatsAppChannel"
|
||||
:is-web-widget-inbox="isAWebWidgetInbox"
|
||||
:is-a-facebook-inbox="isAFacebookInbox"
|
||||
:is-an-email-inbox="isAnEmailChannel"
|
||||
:is-instagram="isInstagramDM"
|
||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||
:in-reply-to="getInReplyToMessage(message)"
|
||||
/>
|
||||
@@ -54,6 +57,8 @@
|
||||
:is-a-tweet="isATweet"
|
||||
:is-a-whatsapp-channel="isAWhatsAppChannel"
|
||||
:is-web-widget-inbox="isAWebWidgetInbox"
|
||||
:is-a-facebook-inbox="isAFacebookInbox"
|
||||
:is-instagram-dm="isInstagramDM"
|
||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||
:in-reply-to="getInReplyToMessage(message)"
|
||||
/>
|
||||
@@ -283,6 +288,9 @@ export default {
|
||||
unreadMessageCount() {
|
||||
return this.currentChat.unread_count || 0;
|
||||
},
|
||||
isInstagramDM() {
|
||||
return this.conversationType === 'instagram_direct_message';
|
||||
},
|
||||
inboxSupportsReplyTo() {
|
||||
const incoming = this.inboxHasFeature(INBOX_FEATURES.REPLY_TO);
|
||||
const outgoing =
|
||||
|
||||
@@ -164,7 +164,7 @@ import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel
|
||||
import ReplyEmailHead from './ReplyEmailHead.vue';
|
||||
import ReplyBottomPanel from 'dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue';
|
||||
import ArticleSearchPopover from 'dashboard/routes/dashboard/helpcenter/components/ArticleSearch/SearchPopover.vue';
|
||||
import MessageSignatureMissingAlert from './MessageSignatureMissingAlert';
|
||||
import MessageSignatureMissingAlert from './MessageSignatureMissingAlert.vue';
|
||||
import Banner from 'dashboard/components/ui/Banner.vue';
|
||||
import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants';
|
||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||
@@ -198,7 +198,7 @@ import {
|
||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||
|
||||
const EmojiInput = () => import('shared/components/emoji/EmojiInput');
|
||||
const EmojiInput = () => import('shared/components/emoji/EmojiInput.vue');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -271,6 +271,11 @@ export default {
|
||||
accountId: 'getCurrentAccountId',
|
||||
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
|
||||
}),
|
||||
currentContact() {
|
||||
return this.$store.getters['contacts/getContact'](
|
||||
this.currentChat.meta.sender.id
|
||||
);
|
||||
},
|
||||
shouldShowReplyToMessage() {
|
||||
return (
|
||||
this.inReplyTo?.id &&
|
||||
@@ -509,6 +514,7 @@ export default {
|
||||
messageVariables() {
|
||||
const variables = getMessageVariables({
|
||||
conversation: this.currentChat,
|
||||
contact: this.currentContact,
|
||||
});
|
||||
return variables;
|
||||
},
|
||||
@@ -1202,6 +1208,7 @@ export default {
|
||||
@apply bg-yellow-50 dark:bg-yellow-200;
|
||||
}
|
||||
}
|
||||
|
||||
.send-button {
|
||||
@apply mb-0;
|
||||
}
|
||||
@@ -1222,6 +1229,7 @@ export default {
|
||||
|
||||
.emoji-dialog--rtl {
|
||||
@apply left-[unset] -right-80;
|
||||
|
||||
&::before {
|
||||
transform: rotate(90deg);
|
||||
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.08));
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="toEmails">
|
||||
<div class="input-group small" :class="{ error: $v.toEmailsVal.$error }">
|
||||
<div class="input-group small" :class="{ error: v$.toEmailsVal.$error }">
|
||||
<label class="input-group-label">
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
|
||||
</label>
|
||||
<div class="input-group-field">
|
||||
<woot-input
|
||||
v-model.trim="$v.toEmailsVal.$model"
|
||||
v-model.trim="v$.toEmailsVal.$model"
|
||||
type="text"
|
||||
:class="{ error: $v.toEmailsVal.$error }"
|
||||
:class="{ error: v$.toEmailsVal.$error }"
|
||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
@@ -17,15 +17,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group-wrap">
|
||||
<div class="input-group small" :class="{ error: $v.ccEmailsVal.$error }">
|
||||
<div class="input-group small" :class="{ error: v$.ccEmailsVal.$error }">
|
||||
<label class="input-group-label">
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
|
||||
</label>
|
||||
<div class="input-group-field">
|
||||
<woot-input
|
||||
v-model.trim="$v.ccEmailsVal.$model"
|
||||
v-model.trim="v$.ccEmailsVal.$model"
|
||||
type="text"
|
||||
:class="{ error: $v.ccEmailsVal.$error }"
|
||||
:class="{ error: v$.ccEmailsVal.$error }"
|
||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
@@ -39,20 +39,20 @@
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.ADD_BCC') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
<span v-if="$v.ccEmailsVal.$error" class="message">
|
||||
<span v-if="v$.ccEmailsVal.$error" class="message">
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.ERROR') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="showBcc" class="input-group-wrap">
|
||||
<div class="input-group small" :class="{ error: $v.bccEmailsVal.$error }">
|
||||
<div class="input-group small" :class="{ error: v$.bccEmailsVal.$error }">
|
||||
<label class="input-group-label">
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
|
||||
</label>
|
||||
<div class="input-group-field">
|
||||
<woot-input
|
||||
v-model.trim="$v.bccEmailsVal.$model"
|
||||
v-model.trim="v$.bccEmailsVal.$model"
|
||||
type="text"
|
||||
:class="{ error: $v.bccEmailsVal.$error }"
|
||||
:class="{ error: v$.bccEmailsVal.$error }"
|
||||
:placeholder="
|
||||
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')
|
||||
"
|
||||
@@ -60,7 +60,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="$v.bccEmailsVal.$error" class="message">
|
||||
<span v-if="v$.bccEmailsVal.$error" class="message">
|
||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.ERROR') }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -137,7 +137,7 @@ export default {
|
||||
this.showBcc = true;
|
||||
},
|
||||
onBlur() {
|
||||
this.$v.$touch();
|
||||
this.v$.$touch();
|
||||
this.$emit('update:bccEmails', this.bccEmailsVal);
|
||||
this.$emit('update:ccEmails', this.ccEmailsVal);
|
||||
this.$emit('update:toEmails', this.toEmailsVal);
|
||||
@@ -149,12 +149,14 @@ export default {
|
||||
.input-group-wrap .message {
|
||||
@apply text-sm text-red-500 dark:text-red-500;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
@apply border-b border-solid border-slate-75 dark:border-slate-700 my-1;
|
||||
|
||||
.input-group-label {
|
||||
@apply border-transparent bg-transparent text-xs font-semibold pl-0;
|
||||
}
|
||||
|
||||
.input-group-field::v-deep input {
|
||||
@apply mb-0 border-transparent;
|
||||
}
|
||||
@@ -162,6 +164,7 @@ export default {
|
||||
|
||||
.input-group.error {
|
||||
@apply border-b-red-500 dark:border-b-red-500;
|
||||
|
||||
.input-group-label {
|
||||
@apply text-red-500 dark:text-red-500;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<mention-box :items="items" @mention-select="handleVariableClick">
|
||||
<mention-box
|
||||
v-if="items.length"
|
||||
type="variable"
|
||||
:items="items"
|
||||
@mention-select="handleVariableClick"
|
||||
>
|
||||
<template slot-scope="{ item }">
|
||||
<span class="text-capitalize variable--list-label">
|
||||
{{ item.description }}
|
||||
@@ -10,6 +15,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { MESSAGE_VARIABLES } from 'shared/constants/messages';
|
||||
import MentionBox from '../mentions/MentionBox.vue';
|
||||
|
||||
@@ -22,7 +28,16 @@ export default {
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
customAttributes: 'attributes/getAttributes',
|
||||
}),
|
||||
items() {
|
||||
return [
|
||||
...this.standardAttributeVariables,
|
||||
...this.customAttributeVariables,
|
||||
];
|
||||
},
|
||||
standardAttributeVariables() {
|
||||
return MESSAGE_VARIABLES.filter(variable => {
|
||||
return (
|
||||
variable.label.includes(this.searchKey) ||
|
||||
@@ -34,6 +49,20 @@ export default {
|
||||
description: variable.label,
|
||||
}));
|
||||
},
|
||||
customAttributeVariables() {
|
||||
return this.customAttributes.map(attribute => {
|
||||
const attributePrefix =
|
||||
attribute.attribute_model === 'conversation_attribute'
|
||||
? 'conversation'
|
||||
: 'contact';
|
||||
|
||||
return {
|
||||
label: `${attributePrefix}.custom_attribute.${attribute.attribute_key}`,
|
||||
key: `${attributePrefix}.custom_attribute.${attribute.attribute_key}`,
|
||||
description: attribute.attribute_description,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleVariableClick(item = {}) {
|
||||
|
||||
+8
-1
@@ -45,7 +45,9 @@ const allKeysRequired = value => {
|
||||
const keys = Object.keys(value);
|
||||
return keys.every(key => value[key]);
|
||||
};
|
||||
import { requiredIf } from 'vuelidate/lib/validators';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
import { requiredIf } from '@vuelidate/validators';
|
||||
export default {
|
||||
props: {
|
||||
template: {
|
||||
@@ -53,6 +55,9 @@ export default {
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
validations: {
|
||||
processedParams: {
|
||||
requiredIfKeysPresent: requiredIf('variables'),
|
||||
@@ -149,9 +154,11 @@ footer {
|
||||
@apply ml-2.5;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
@apply bg-red-100 dark:bg-red-100 rounded-md text-red-800 dark:text-red-800 p-2.5 text-center;
|
||||
}
|
||||
|
||||
.template-input {
|
||||
@apply bg-slate-25 dark:bg-slate-900 text-slate-700 dark:text-slate-100;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import 'dashboard/assets/scss/variables';
|
||||
|
||||
.file {
|
||||
display: flex;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import emailValidator from 'vuelidate/lib/validators/email';
|
||||
import { email as emailValidator } from '@vuelidate/validators';
|
||||
|
||||
export const validEmailsByComma = value => {
|
||||
if (!value.length) return true;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
class="cursor-pointer py-2 pr-1.5 pl-2 rounded-tl-md rounded-bl-md flex items-center justify-center gap-1.5 bg-slate-25 dark:bg-slate-700 h-10 w-14"
|
||||
@click="toggleCountryDropdown"
|
||||
>
|
||||
<h5 v-if="activeCountry.emoji" class="mb-0">
|
||||
<h5 v-if="activeCountry" class="mb-0">
|
||||
{{ activeCountry.emoji }}
|
||||
</h5>
|
||||
<fluent-icon v-else icon="globe" class="fluent-icon" size="16" />
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
<template>
|
||||
<div v-if="items.length" ref="mentionsListContainer" class="mention--box">
|
||||
<div
|
||||
ref="mentionsListContainer"
|
||||
class="bg-white dark:bg-slate-800 rounded-md overflow-auto absolute w-full z-20 pb-0 shadow-md left-0 bottom-full max-h-[9.75rem] border border-solid border-slate-100 dark:border-slate-700 mention--box"
|
||||
>
|
||||
<ul class="vertical dropdown menu">
|
||||
<woot-dropdown-item
|
||||
v-for="(item, index) in items"
|
||||
:id="`mention-item-${index}`"
|
||||
:key="item.key"
|
||||
class="!mb-0"
|
||||
@mouseover="onHover(index)"
|
||||
>
|
||||
<woot-button
|
||||
class="canned-item__button"
|
||||
:variant="index === selectedIndex ? '' : 'clear'"
|
||||
:class="{ active: index === selectedIndex }"
|
||||
<button
|
||||
class="flex group flex-col gap-0.5 overflow-hidden cursor-pointer items-start py-2.5 px-2.5 justify-center w-full h-full text-left hover:bg-woot-50 dark:hover:bg-woot-800 border-b border-solid border-slate-100 dark:border-slate-700"
|
||||
:class="{
|
||||
' bg-woot-25 dark:bg-woot-800': index === selectedIndex,
|
||||
}"
|
||||
@click="onListItemSelection(index)"
|
||||
>
|
||||
<strong>{{ item.label }}</strong> - {{ item.description }}
|
||||
</woot-button>
|
||||
<p
|
||||
class="text-slate-900 dark:text-slate-100 group-hover:text-woot-500 dark:group-hover:text-woot-500 font-medium mb-0 text-sm overflow-hidden text-ellipsis whitespace-nowrap min-w-0 max-w-full"
|
||||
:class="{
|
||||
'text-woot-500 dark:text-woot-500': index === selectedIndex,
|
||||
}"
|
||||
>
|
||||
{{ item.description }}
|
||||
</p>
|
||||
<p
|
||||
class="text-slate-500 dark:text-slate-300 group-hover:text-woot-500 dark:group-hover:text-woot-500 mb-0 text-xs overflow-hidden text-ellipsis whitespace-nowrap min-w-0 max-w-full"
|
||||
:class="{
|
||||
'text-woot-500 dark:text-woot-500': index === selectedIndex,
|
||||
}"
|
||||
>
|
||||
{{ variableKey(item) }}
|
||||
</p>
|
||||
</button>
|
||||
</woot-dropdown-item>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -29,6 +49,10 @@ export default {
|
||||
type: Array,
|
||||
default: () => {},
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'canned',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -73,28 +97,17 @@ export default {
|
||||
onSelect() {
|
||||
this.$emit('mention-select', this.items[this.selectedIndex]);
|
||||
},
|
||||
variableKey(item = {}) {
|
||||
return this.type === 'variable' ? `{{${item.label}}}` : `/${item.label}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mention--box {
|
||||
@apply bg-white dark:bg-slate-700 rounded-md overflow-auto absolute w-full z-20 pt-2 px-2 pb-0 shadow-md left-0 bottom-full max-h-[9.75rem] border-t border-solid border-slate-75 dark:border-slate-800;
|
||||
|
||||
.dropdown-menu__item:last-child {
|
||||
@apply pb-1;
|
||||
}
|
||||
|
||||
.active {
|
||||
@apply text-white dark:text-white;
|
||||
|
||||
&:hover {
|
||||
@apply bg-woot-700 dark:bg-woot-700;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
@apply transition-none h-8 leading-[1.4];
|
||||
.dropdown-menu__item:last-child > button {
|
||||
@apply border-0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<woot-input
|
||||
v-model="value"
|
||||
type="text"
|
||||
:class="{ error: $v.value.$error }"
|
||||
:class="{ error: v$.value.$error }"
|
||||
:placeholder="confirmPlaceHolderText"
|
||||
@blur="$v.value.$touch"
|
||||
@blur="v$.value.$touch"
|
||||
/>
|
||||
<div class="button-wrapper">
|
||||
<woot-button color-scheme="alert" :is-disabled="$v.value.$invalid">
|
||||
<woot-button color-scheme="alert" :is-disabled="v$.value.$invalid">
|
||||
{{ confirmText }}
|
||||
</woot-button>
|
||||
<woot-button class="clear" @click.prevent="closeModal">
|
||||
@@ -23,14 +23,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import Modal from '../../Modal.vue';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
},
|
||||
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
@@ -61,6 +61,9 @@ export default {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return { v$: useVuelidate() };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
|
||||
@@ -10,6 +10,7 @@ export class DataManager {
|
||||
|
||||
async initDb() {
|
||||
if (this.db) return this.db;
|
||||
const dbName = `cw-store-${this.accountId}`;
|
||||
this.db = await openDB(`cw-store-${this.accountId}`, DATA_VERSION, {
|
||||
upgrade(db) {
|
||||
db.createObjectStore('cache-keys');
|
||||
@@ -19,6 +20,13 @@ export class DataManager {
|
||||
},
|
||||
});
|
||||
|
||||
// Store the database name in LocalStorage
|
||||
const dbNames = JSON.parse(localStorage.getItem('cw-idb-names') || '[]');
|
||||
if (!dbNames.includes(dbName)) {
|
||||
dbNames.push(dbName);
|
||||
localStorage.setItem('cw-idb-names', JSON.stringify(dbNames));
|
||||
}
|
||||
|
||||
return this.db;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ export const getCustomFields = ({ standardFields, customAttributes }) => {
|
||||
type: attribute.attribute_display_type,
|
||||
values: attribute.attribute_values,
|
||||
field_type: attribute.attribute_model,
|
||||
regex_pattern: attribute.regex_pattern,
|
||||
regex_cue: attribute.regex_cue,
|
||||
required: false,
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
@@ -44,4 +44,18 @@ export default {
|
||||
created_at: '2021-11-29T10:20:04.563Z',
|
||||
},
|
||||
],
|
||||
customAttributesWithRegex: [
|
||||
{
|
||||
id: 2,
|
||||
attribute_description: 'Test contact Attribute',
|
||||
attribute_display_name: 'Test contact Attribute',
|
||||
attribute_display_type: 'text',
|
||||
attribute_key: 'test_contact_attribute',
|
||||
attribute_model: 'contact_attribute',
|
||||
attribute_values: Array(0),
|
||||
created_at: '2023-09-20T10:20:04.563Z',
|
||||
regex_pattern: '^w+$',
|
||||
regex_cue: 'It should be a combination of alphabets and numbers',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
} from '../preChat';
|
||||
import inboxFixture from './inboxFixture';
|
||||
|
||||
const { customFields, customAttributes } = inboxFixture;
|
||||
const { customFields, customAttributes, customAttributesWithRegex } =
|
||||
inboxFixture;
|
||||
describe('#Pre chat Helpers', () => {
|
||||
describe('getPreChatFields', () => {
|
||||
it('should return correct pre-chat fields form options passed', () => {
|
||||
@@ -27,7 +28,6 @@ describe('#Pre chat Helpers', () => {
|
||||
placeholder: 'Please enter your email address',
|
||||
type: 'email',
|
||||
field_type: 'standard',
|
||||
|
||||
required: false,
|
||||
enabled: false,
|
||||
},
|
||||
@@ -71,6 +71,26 @@ describe('#Pre chat Helpers', () => {
|
||||
values: [],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(
|
||||
getCustomFields({
|
||||
standardFields: { pre_chat_fields: customFields.pre_chat_fields },
|
||||
customAttributes: customAttributesWithRegex,
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
enabled: false,
|
||||
label: 'Test contact Attribute',
|
||||
placeholder: 'Test contact Attribute',
|
||||
name: 'test_contact_attribute',
|
||||
required: false,
|
||||
field_type: 'contact_attribute',
|
||||
type: 'text',
|
||||
values: [],
|
||||
regex_pattern: '^w+$',
|
||||
regex_cue: 'It should be a combination of alphabets and numbers',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"FILTER": {
|
||||
"TITLE": "Filter Conversations",
|
||||
"SUBTITLE": "Add filters below and hit 'Apply filters' to filter conversations.",
|
||||
"TITLE": "Filter conversations",
|
||||
"SUBTITLE": "Add your filters below and hit 'Apply filters' to cut through the chat clutter.",
|
||||
"EDIT_CUSTOM_FILTER": "Edit Folder",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
|
||||
"ADD_NEW_FILTER": "Add Filter",
|
||||
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
|
||||
"ADD_NEW_FILTER": "Add filter",
|
||||
"FILTER_DELETE_ERROR": "Oops, looks like we can't save nothing! Please add at least one filter to save it.",
|
||||
"SUBMIT_BUTTON_LABEL": "Apply filters",
|
||||
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||
"CANCEL_BUTTON_LABEL": "Cancel",
|
||||
"CLEAR_BUTTON_LABEL": "Clear Filters",
|
||||
"EMPTY_VALUE_ERROR": "Value is required",
|
||||
"CLEAR_BUTTON_LABEL": "Clear filters",
|
||||
"FOLDER_LABEL": "Folder Name",
|
||||
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||
"EMPTY_VALUE_ERROR": "Value is required.",
|
||||
"TOOLTIP_LABEL": "Filter conversations",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "AND",
|
||||
@@ -36,44 +36,44 @@
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"STATUS": "Status",
|
||||
"ASSIGNEE_NAME": "Assignee Name",
|
||||
"INBOX_NAME": "Inbox Name",
|
||||
"TEAM_NAME": "Team Name",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation Identifier",
|
||||
"CAMPAIGN_NAME": "Campaign Name",
|
||||
"ASSIGNEE_NAME": "Assignee name",
|
||||
"INBOX_NAME": "Inbox name",
|
||||
"TEAM_NAME": "Team name",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation identifier",
|
||||
"CAMPAIGN_NAME": "Campaign name",
|
||||
"LABELS": "Labels",
|
||||
"BROWSER_LANGUAGE": "Browser Language",
|
||||
"BROWSER_LANGUAGE": "Browser language",
|
||||
"PRIORITY": "Priority",
|
||||
"COUNTRY_NAME": "Country Name",
|
||||
"COUNTRY_NAME": "Country name",
|
||||
"REFERER_LINK": "Referer link",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "List",
|
||||
"CUSTOM_ATTRIBUTE_TEXT": "Text",
|
||||
"CUSTOM_ATTRIBUTE_NUMBER": "Number",
|
||||
"CUSTOM_ATTRIBUTE_LINK": "Link",
|
||||
"CUSTOM_ATTRIBUTE_CHECKBOX": "Checkbox",
|
||||
"CREATED_AT": "Created At",
|
||||
"LAST_ACTIVITY": "Last Activity"
|
||||
"CREATED_AT": "Created at",
|
||||
"LAST_ACTIVITY": "Last activity"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "Standard Filters",
|
||||
"ADDITIONAL_FILTERS": "Additional Filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom Attributes"
|
||||
"STANDARD_FILTERS": "Standard filters",
|
||||
"ADDITIONAL_FILTERS": "Additional filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom attributes"
|
||||
},
|
||||
"CUSTOM_VIEWS": {
|
||||
"ADD": {
|
||||
"TITLE": "Do you want to save this filter?",
|
||||
"LABEL": "Name this filter",
|
||||
"PLACEHOLDER": "Enter a name for this filter",
|
||||
"ERROR_MESSAGE": "Name is required",
|
||||
"PLACEHOLDER": "Name your filter to refer it later.",
|
||||
"ERROR_MESSAGE": "Name is required.",
|
||||
"SAVE_BUTTON": "Save filter",
|
||||
"CANCEL_BUTTON": "Cancel",
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating folder"
|
||||
"SUCCESS_MESSAGE": "Folder created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating segment"
|
||||
"SUCCESS_MESSAGE": "Segment created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating segment."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
@@ -83,19 +83,19 @@
|
||||
"DELETE_BUTTON": "Delete filter",
|
||||
"MODAL": {
|
||||
"CONFIRM": {
|
||||
"TITLE": "Confirm Deletion",
|
||||
"TITLE": "Confirm deletion",
|
||||
"MESSAGE": "Are you sure to delete the filter ",
|
||||
"YES": "Yes, Delete",
|
||||
"NO": "No, Keep it"
|
||||
"YES": "Yes, delete",
|
||||
"NO": "No, keep it"
|
||||
}
|
||||
},
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting folder"
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting segment"
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting segment."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
{
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "Loading Editor...",
|
||||
"HEADER_BTN_TXT": "Add Bot Configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent bots allows you to automate the conversations</p>",
|
||||
"LOADING_EDITOR": "Loading editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot Name",
|
||||
"PLACEHOLDER": "Give your bot a name",
|
||||
"ERROR": "Bot name is required"
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot Description",
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above",
|
||||
"API_ERROR": "Your CSML configuration is invalid, please fix it and try again."
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "You can set an agent bot from the list to this inbox. The bot can initially handle the conversation and transfer it to an agent when needed.",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"SUBMIT": "Update",
|
||||
"DISCONNECT": "Disconnect Bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot, please try again later",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot, please try again later",
|
||||
"SELECT_PLACEHOLDER": "Select Bot"
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully",
|
||||
"ERROR_MESSAGE": "Could not add bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No Bots found, you can create a bot by clicking the 'Configure new bot' Button ↗",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TYPE": "Bot Type"
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Delete",
|
||||
"TITLE": "Delete Bot",
|
||||
"TITLE": "Delete bot",
|
||||
"SUBMIT": "Delete",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not able to delete bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "Edit",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TITLE": "Edit Bot",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "Webhook Bot",
|
||||
"CSML": "CSML Bot"
|
||||
"WEBHOOK": "Webhook bot",
|
||||
"CSML": "CSML bot"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
{
|
||||
"BULK_ACTION": {
|
||||
"CONVERSATIONS_SELECTED": "%{conversationCount} conversations selected",
|
||||
"AGENT_SELECT_LABEL": "Select Agent",
|
||||
"AGENT_SELECT_LABEL": "Select agent",
|
||||
"ASSIGN_CONFIRMATION_LABEL": "Are you sure to assign %{conversationCount} %{conversationLabel} to",
|
||||
"UNASSIGN_CONFIRMATION_LABEL": "Are you sure to unassign %{conversationCount} %{conversationLabel}?",
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_LABEL": "Assign",
|
||||
"YES": "Yes",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign Agent",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations, please try again",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations, please try again",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "Conversations visible on this page are only selected.",
|
||||
"AGENT_LIST_LOADING": "Loading Agents",
|
||||
"AGENT_LIST_LOADING": "Loading agents",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "Change status",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply.",
|
||||
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
|
||||
"UPDATE_FAILED": "Failed to update conversations, please try again"
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "Assign Labels",
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"NO_LABELS_FOUND": "No labels found for",
|
||||
"ASSIGN_SELECTED_LABELS": "Assign selected labels",
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign labels, please try again"
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "Select Team",
|
||||
"TEAM_SELECT_LABEL": "Select team",
|
||||
"NONE": "None",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign team, please try again"
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Canned Responses",
|
||||
"HEADER_BTN_TXT": "Add Canned Response",
|
||||
"LOADING": "Fetching Canned Responses",
|
||||
"SEARCH_404": "There are no items matching this query",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are saved reply templates which can be used to quickly send out a reply to a conversation. </p><p> For creating a Canned Response, just click on the <b>Add Canned Response</b>. You can also edit or delete an existing Canned Response by clicking on the Edit or Delete button </p><p> Canned responses are used with the help of <b>Short Codes</b>. Agents can access canned responses while on a chat by typing <b>'/'</b> followed by the short code. </p>",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"SEARCH_404": "There are no items matching this query.",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are pre-written reply templates that help you quickly respond to a conversation. To insert a canned response during a chat, agents can type a short code preceded by a '/' character. </p><p> You can manage your canned responses from this page or create new ones using the \"Add canned response\" button.</p><p>Open the <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\">Canned Responses handbook</a> in another tab for a helping hand.</p><p>Also, check out the all-new <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">Canned Responses Library</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "There are no canned responses available in this account.",
|
||||
"TITLE": "Manage canned responses",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to tickets.",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"TABLE_HEADER": [
|
||||
"Short Code",
|
||||
"Short code",
|
||||
"Content",
|
||||
"Actions"
|
||||
]
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Add Canned Response",
|
||||
"DESC": "Canned Responses are saved reply templates which can be used to quickly send out reply to conversation.",
|
||||
"TITLE": "Add canned response",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Short Code",
|
||||
"PLACEHOLDER": "Please enter a short code",
|
||||
"ERROR": "Short Code is required"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a short code.",
|
||||
"ERROR": "Short Code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Content",
|
||||
"PLACEHOLDER": "Please enter a content",
|
||||
"ERROR": "Content is required"
|
||||
"LABEL": "Message",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Submit"
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Canned Response added successfully",
|
||||
"ERROR_MESSAGE": "Could not create canned response. Please try again later."
|
||||
"SUCCESS_MESSAGE": "Canned response added successfully.",
|
||||
"ERROR_MESSAGE": "Could not connect to Woot server. Please try again."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Edit Canned Response",
|
||||
"TITLE": "Edit canned response",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Short Code",
|
||||
"PLACEHOLDER": "Please enter a shortcode",
|
||||
"ERROR": "Short Code is required"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a shortcode.",
|
||||
"ERROR": "Short code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Content",
|
||||
"PLACEHOLDER": "Please enter a content",
|
||||
"ERROR": "Content is required"
|
||||
"LABEL": "Message",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Submit"
|
||||
},
|
||||
"BUTTON_TEXT": "Edit",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Canned Response updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update canned response. Please try again later."
|
||||
"SUCCESS_MESSAGE": "Canned response is updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not connect to Woot server. Please try again."
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Delete",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Canned response deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not delete canned response. Please try again later."
|
||||
"SUCCESS_MESSAGE": "Canned response deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not connect to Woot server. Please try again."
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Confirm Deletion",
|
||||
"TITLE": "Confirm deletion",
|
||||
"MESSAGE": "Are you sure to delete ",
|
||||
"YES": "Yes, Delete ",
|
||||
"NO": "No, Keep "
|
||||
"YES": "Yes, delete ",
|
||||
"NO": "No, keep "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,18 +51,30 @@
|
||||
"ACTIVE": "Last activity"
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_FILTER_ITEMS": {
|
||||
"latest": {
|
||||
"TEXT": "Last activity"
|
||||
"SORT_ORDER_ITEMS": {
|
||||
"last_activity_at_asc": {
|
||||
"TEXT": "Last activity: Oldest first"
|
||||
},
|
||||
"sort_on_created_at": {
|
||||
"TEXT": "Created at"
|
||||
"last_activity_at_desc": {
|
||||
"TEXT": "Last activity: Newest first"
|
||||
},
|
||||
"sort_on_priority": {
|
||||
"TEXT": "Priority"
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
},
|
||||
"sort_on_waiting_since": {
|
||||
"TEXT": "Pending Response"
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
"SAVE_CONTACT": "Save",
|
||||
"UPLOADING_ATTACHMENTS": "Uploading attachments...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"UNSUPPORTED_MESSAGE": "This message is unsupported.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
|
||||
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
|
||||
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
|
||||
"NO_RESPONSE": "No response",
|
||||
@@ -139,6 +142,7 @@
|
||||
"PRIVATE_NOTE": "Private Note",
|
||||
"SEND": "Send",
|
||||
"CREATE": "Add Note",
|
||||
"INSERT_READ_MORE": "Read more",
|
||||
"DISMISS_REPLY": "Dismiss reply",
|
||||
"REPLYING_TO": "Replying to:",
|
||||
"TIP_FORMAT_ICON": "Show rich text editor",
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"TEXT": "Disconnected from Chatwoot"
|
||||
"OFFLINE": "Offline"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "Refresh"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"HEADER": {
|
||||
"FILTER": "Filter by",
|
||||
"SORT": "Sort by",
|
||||
"LOCALE": "Locale",
|
||||
"SETTINGS_BUTTON": "Settings",
|
||||
"NEW_BUTTON": "New Article",
|
||||
"DROPDOWN_OPTIONS": {
|
||||
@@ -15,6 +16,12 @@
|
||||
"MINE": "My Articles",
|
||||
"DRAFT": "Draft Articles",
|
||||
"ARCHIVED": "Archived Articles"
|
||||
},
|
||||
"LOCALE_SELECT": {
|
||||
"TITLE": "Select locale",
|
||||
"PLACEHOLDER": "Select locale",
|
||||
"NO_RESULT": "No locale found",
|
||||
"SEARCH_PLACEHOLDER": "Search locale"
|
||||
}
|
||||
},
|
||||
"EDIT_HEADER": {
|
||||
@@ -76,6 +83,9 @@
|
||||
},
|
||||
"ARTICLE_SEARCH_RESULT": {
|
||||
"UNCATEGORIZED": "Uncategorized",
|
||||
"SEARCH_RESULTS": "Search results for %{query}",
|
||||
"EMPTY_TEXT": "Search for articles to insert into replies.",
|
||||
"SEARCH_LOADER": "Searching...",
|
||||
"INSERT_ARTICLE": "Insert",
|
||||
"NO_RESULT": "No articles found",
|
||||
"COPY_LINK": "Copy article link to clipboard",
|
||||
@@ -220,7 +230,10 @@
|
||||
"LOGO": {
|
||||
"LABEL": "Logo",
|
||||
"UPLOAD_BUTTON": "Upload logo",
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header."
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header.",
|
||||
"IMAGE_UPLOAD_SUCCESS": "Logo uploaded successfully",
|
||||
"IMAGE_UPLOAD_ERROR": "Logo deleted successfully",
|
||||
"IMAGE_DELETE_ERROR": "Error while deleting logo"
|
||||
},
|
||||
"NAME": {
|
||||
"LABEL": "Name",
|
||||
@@ -426,6 +439,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ARTICLE_SEARCH": {
|
||||
"TITLE": "Search articles",
|
||||
"PLACEHOLDER": "Search articles",
|
||||
"NO_RESULT": "No articles found",
|
||||
"SEARCHING": "Searching...",
|
||||
"SEARCH_BUTTON": "Search",
|
||||
"INSERT_ARTICLE": "Insert link",
|
||||
"IFRAME_ERROR": "URL is empty or invalid. Unable to display content.",
|
||||
"OPEN_ARTICLE_SEARCH": "Insert article from Help Center",
|
||||
"SUCCESS_ARTICLE_INSERTED": "Article inserted successfully",
|
||||
"PREVIEW_LINK": "Preview article",
|
||||
"CANCEL": "Close",
|
||||
"BACK": "Back",
|
||||
"BACK_RESULTS": "Back to results"
|
||||
},
|
||||
"UPGRADE_PAGE": {
|
||||
"TITLE": "Help Center",
|
||||
"DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"FILTER": {
|
||||
"TITLE": "تصفية المحادثات",
|
||||
"SUBTITLE": "إضافة فلاتر أدناه واضغط على 'إرسال' لتصفية المحادثات.",
|
||||
"SUBTITLE": "Add your filters below and hit 'Apply filters' to cut through the chat clutter.",
|
||||
"EDIT_CUSTOM_FILTER": "Edit Folder",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
|
||||
"ADD_NEW_FILTER": "إضافة عامل تصفية",
|
||||
"FILTER_DELETE_ERROR": "يجب أن يكون لديك عامل تصفية واحد على الأقل للحفظ",
|
||||
"ADD_NEW_FILTER": "Add filter",
|
||||
"FILTER_DELETE_ERROR": "Oops, looks like we can't save nothing! Please add at least one filter to save it.",
|
||||
"SUBMIT_BUTTON_LABEL": "تطبيق عامل التصفية",
|
||||
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||
"CANCEL_BUTTON_LABEL": "إلغاء",
|
||||
"CLEAR_BUTTON_LABEL": "مسح عامل التصفية",
|
||||
"EMPTY_VALUE_ERROR": "القيمة مطلوبة",
|
||||
"CLEAR_BUTTON_LABEL": "Clear filters",
|
||||
"FOLDER_LABEL": "Folder Name",
|
||||
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||
"EMPTY_VALUE_ERROR": "القيمة مطلوبة.",
|
||||
"TOOLTIP_LABEL": "تصفية المحادثات",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "و",
|
||||
@@ -36,15 +36,15 @@
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"STATUS": "الحالة",
|
||||
"ASSIGNEE_NAME": "اسم المحال إليه",
|
||||
"INBOX_NAME": "اسم صندوق الوارد لقناة التواصل",
|
||||
"ASSIGNEE_NAME": "Assignee name",
|
||||
"INBOX_NAME": "اسم صندوق الوارد",
|
||||
"TEAM_NAME": "اسم الفريق",
|
||||
"CONVERSATION_IDENTIFIER": "معرف المحادثة",
|
||||
"CAMPAIGN_NAME": "اسم الحملة",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation identifier",
|
||||
"CAMPAIGN_NAME": "Campaign name",
|
||||
"LABELS": "الوسوم",
|
||||
"BROWSER_LANGUAGE": "لغة المتصفح",
|
||||
"BROWSER_LANGUAGE": "Browser language",
|
||||
"PRIORITY": "الأولوية",
|
||||
"COUNTRY_NAME": "اسم الدولة",
|
||||
"COUNTRY_NAME": "Country name",
|
||||
"REFERER_LINK": "رابط المرجع",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "القائمة",
|
||||
"CUSTOM_ATTRIBUTE_TEXT": "النص",
|
||||
@@ -52,28 +52,28 @@
|
||||
"CUSTOM_ATTRIBUTE_LINK": "الرابط",
|
||||
"CUSTOM_ATTRIBUTE_CHECKBOX": "مربع",
|
||||
"CREATED_AT": "تم إنشاؤها في",
|
||||
"LAST_ACTIVITY": "آخر نشاط"
|
||||
"LAST_ACTIVITY": "النشاط الأخير"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "الفلاتر القياسية",
|
||||
"ADDITIONAL_FILTERS": "فلاتر إضافية",
|
||||
"CUSTOM_ATTRIBUTES": "سمات مخصصة"
|
||||
"STANDARD_FILTERS": "Standard filters",
|
||||
"ADDITIONAL_FILTERS": "Additional filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom attributes"
|
||||
},
|
||||
"CUSTOM_VIEWS": {
|
||||
"ADD": {
|
||||
"TITLE": "هل تريد حفظ هذا الفلتر؟",
|
||||
"LABEL": "تسمية هذا الفلتر",
|
||||
"PLACEHOLDER": "أدخل اسم لهذا الفلتر",
|
||||
"ERROR_MESSAGE": "الاسم مطلوب",
|
||||
"PLACEHOLDER": "Name your filter to refer it later.",
|
||||
"ERROR_MESSAGE": "الاسم مطلوب.",
|
||||
"SAVE_BUTTON": "حفظ الفلتر",
|
||||
"CANCEL_BUTTON": "إلغاء",
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "تم إنشاء طريقة عرض مخصصة بنجاح",
|
||||
"ERROR_MESSAGE": "خطأ أثناء إنشاء طريقة عرض مخصصة"
|
||||
"SUCCESS_MESSAGE": "تم إنشاء طريقة عرض مخصصة بنجاح.",
|
||||
"ERROR_MESSAGE": "خطأ أثناء إنشاء طريقة عرض مخصصة."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "تم إنشاء طريقة عرض مخصصة بنجاح",
|
||||
"ERROR_MESSAGE": "خطأ أثناء إنشاء طريقة عرض مخصصة"
|
||||
"SUCCESS_MESSAGE": "تم إنشاء طريقة عرض مخصصة بنجاح.",
|
||||
"ERROR_MESSAGE": "خطأ أثناء إنشاء طريقة عرض مخصصة."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
@@ -85,17 +85,17 @@
|
||||
"CONFIRM": {
|
||||
"TITLE": "تأكيد الحذف",
|
||||
"MESSAGE": "هل أنت متأكد من حذف الفلتر ",
|
||||
"YES": "نعم، احذف",
|
||||
"YES": "Yes, delete",
|
||||
"NO": "لا، احتفظ به"
|
||||
}
|
||||
},
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "تم حذف طريقة عرض مخصصة بنجاح",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء حذف المجلد"
|
||||
"SUCCESS_MESSAGE": "تم حذف طريقة عرض مخصصة بنجاح.",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء حذف المجلد."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "تم حذف العرض المخصص بنجاح",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء حذف طريقة عرض مخصصة"
|
||||
"SUCCESS_MESSAGE": "تم حذف العرض المخصص بنجاح.",
|
||||
"ERROR_MESSAGE": "حدث خطأ أثناء حذف طريقة عرض مخصصة."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
{
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "Loading Editor...",
|
||||
"HEADER_BTN_TXT": "Add Bot Configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent bots allows you to automate the conversations</p>",
|
||||
"LOADING_EDITOR": "Loading editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot Name",
|
||||
"PLACEHOLDER": "Give your bot a name",
|
||||
"ERROR": "Bot name is required"
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot Description",
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above",
|
||||
"API_ERROR": "Your CSML configuration is invalid, please fix it and try again."
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "You can set an agent bot from the list to this inbox. The bot can initially handle the conversation and transfer it to an agent when needed.",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"SUBMIT": "تحديث",
|
||||
"DISCONNECT": "Disconnect Bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot, please try again later",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot, please try again later",
|
||||
"SELECT_PLACEHOLDER": "Select Bot"
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully",
|
||||
"ERROR_MESSAGE": "Could not add bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No Bots found, you can create a bot by clicking the 'Configure new bot' Button ↗",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TYPE": "Bot Type"
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "حذف",
|
||||
"TITLE": "Delete Bot",
|
||||
"TITLE": "Delete bot",
|
||||
"SUBMIT": "حذف",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not able to delete bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "تعديل",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TITLE": "Edit Bot",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "Webhook Bot",
|
||||
"CSML": "CSML Bot"
|
||||
"WEBHOOK": "Webhook bot",
|
||||
"CSML": "CSML bot"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,34 +7,34 @@
|
||||
"GO_BACK_LABEL": "العودة للخلف",
|
||||
"ASSIGN_LABEL": "تكليف",
|
||||
"YES": "نعم",
|
||||
"ASSIGN_AGENT_TOOLTIP": "إسناد وكيل",
|
||||
"ASSIGN_AGENT_TOOLTIP": "تعيين وكيل",
|
||||
"ASSIGN_TEAM_TOOLTIP": "تعيين فريق",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين المحادثات بنجاح",
|
||||
"ASSIGN_FAILED": "فشل في تعيين المحادثات، الرجاء المحاولة مرة أخرى",
|
||||
"RESOLVE_SUCCESFUL": "تم تسوية المحادثات بنجاح",
|
||||
"RESOLVE_FAILED": "فشل في حل المحادثات، يرجى المحاولة مرة أخرى",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين المحادثات بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"RESOLVE_SUCCESFUL": "تم تسوية المحادثات بنجاح.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "المحادثات المرئية في هذه الصفحة هي المحددة فقط.",
|
||||
"AGENT_LIST_LOADING": "تحميل الوكلاء",
|
||||
"AGENT_LIST_LOADING": "جاري تحميل الوكلاء",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "تغيير الحالة",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "غفوة حتى الرد القادم",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "غفوة حتى الرد القادم.",
|
||||
"UPDATE_SUCCESFUL": "تم تحديث حالة المحادثة بنجاح.",
|
||||
"UPDATE_FAILED": "فشل تحديث المحادثات، الرجاء المحاولة مرة أخرى"
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "تعيين التسميات",
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"NO_LABELS_FOUND": "لم يتم العثور على تسميات لـ",
|
||||
"ASSIGN_SELECTED_LABELS": "تعيين التسميات المحددة",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين التسميات بنجاح",
|
||||
"ASSIGN_FAILED": "فشل في تعيين التسميات ، الرجاء المحاولة مرة أخرى"
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين التسميات بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "اختيار فريق",
|
||||
"NONE": "لا شيء",
|
||||
"NO_TEAMS_AVAILABLE": "لا توجد فرق مضافة إلى هذا الحساب حتى الآن.",
|
||||
"ASSIGN_SELECTED_TEAMS": "تعيين فريق محدد",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين الفرق بنجاح",
|
||||
"ASSIGN_FAILED": "فشل تعيين الفريق، الرجاء المحاولة مرة أخرى"
|
||||
"ASSIGN_SELECTED_TEAMS": "تعيين فريق محدد.",
|
||||
"ASSIGN_SUCCESFUL": "تم تعيين الفرق بنجاح.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "الردود السريعة",
|
||||
"HEADER_BTN_TXT": "إضافة رد جاهز",
|
||||
"LOADING": "جاري جلب الردود الجاهزة",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام",
|
||||
"SIDEBAR_TXT": "<p><b>الردود الجاهزة</b> </p><p> الردود الجاهزة هي عبارة عن قوالب يتم إعدادها مسبقاً لاستخدامها في كتابة الرسائل والردود للإجابة على اكثر الاسئلة شيوعاً. </p><p> لإضافة قالب جديد، فقط انقر على <b>إضافة رد جاهز</b>. يمكنك أيضاً تعديل أو حذف الردود الجاهزة الأخرى بالنقر على زر التحرير أو الحذف </p><p> يتم تسهيل استخدام الردود المسبقة بواسطة <b>رموز مختصرة</b> لتسريع البحث والوصول إليها. يمكن للموظفين الوصول إلى قوالب الردود الجاهزة أثناء الدردشة عن طريق الضغط على زر <b>'/'</b> ومن ثم الاختصار الخاص بالقالب المراد إدخاله في مربع النص. </p>",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام.",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are pre-written reply templates that help you quickly respond to a conversation. To insert a canned response during a chat, agents can type a short code preceded by a '/' character. </p><p> You can manage your canned responses from this page or create new ones using the \"Add canned response\" button.</p><p>Open the <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\">Canned Responses handbook</a> in another tab for a helping hand.</p><p>Also, check out the all-new <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">Canned Responses Library</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "لا توجد ردود جاهزة متوفرة في هذا الحساب.",
|
||||
"TITLE": "إدارة الردود الجاهزة",
|
||||
"DESC": "الردود الجاهزة هي قوالب رسائل معدة مسبقاً يمكن استخدامها لتسريع كتابة الردود في المحادثات.",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"TABLE_HEADER": [
|
||||
"الرمز المختصر",
|
||||
"Short code",
|
||||
"المحتوى",
|
||||
"الإجراءات"
|
||||
]
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "إضافة رد جاهز",
|
||||
"DESC": "الردود الجاهزة هي قوالب رسائل معدة مسبقاً يمكن استخدامها لتسريع كتابة الردود في المحادثات.",
|
||||
"TITLE": "Add canned response",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "الرمز المختصر",
|
||||
"PLACEHOLDER": "الرجاء إدخال رمز مختصر",
|
||||
"ERROR": "الرمز المختصر مطلوب"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a short code.",
|
||||
"ERROR": "Short Code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "المحتوى",
|
||||
"PLACEHOLDER": "الرجاء إدخال محتوى",
|
||||
"ERROR": "المحتوى مطلوب"
|
||||
"LABEL": "رسالة",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "إرسال"
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم إضافة قالب الرد الجاهز بنجاح",
|
||||
"SUCCESS_MESSAGE": "Canned response added successfully.",
|
||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "تعديل قالب الرد الجاهز",
|
||||
"TITLE": "Edit canned response",
|
||||
"CANCEL_BUTTON_TEXT": "إلغاء",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "الرمز المختصر",
|
||||
"PLACEHOLDER": "الرجاء إدخال رمز مختصر",
|
||||
"ERROR": "الرمز المختصر مطلوب"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a shortcode.",
|
||||
"ERROR": "Short code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "المحتوى",
|
||||
"PLACEHOLDER": "الرجاء إدخال محتوى",
|
||||
"ERROR": "المحتوى مطلوب"
|
||||
"LABEL": "رسالة",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "الرسالة مطلوبة."
|
||||
},
|
||||
"SUBMIT": "إرسال"
|
||||
},
|
||||
"BUTTON_TEXT": "تعديل",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم تحديث قالب الرد الجاهز بنجاح",
|
||||
"SUCCESS_MESSAGE": "Canned response is updated successfully.",
|
||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "حذف",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "تم حذف قالب الرد الجاهز بنجاح",
|
||||
"SUCCESS_MESSAGE": "Canned response deleted successfully.",
|
||||
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "تأكيد الحذف",
|
||||
"MESSAGE": "هل أنت متأكد من الحذف ",
|
||||
"YES": "نعم، احذف ",
|
||||
"NO": "لا، احتفظ "
|
||||
"YES": "Yes, delete ",
|
||||
"NO": "No, keep "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,18 +51,30 @@
|
||||
"ACTIVE": "النشاط الأخير"
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_FILTER_ITEMS": {
|
||||
"latest": {
|
||||
"TEXT": "النشاط الأخير"
|
||||
"SORT_ORDER_ITEMS": {
|
||||
"last_activity_at_asc": {
|
||||
"TEXT": "Last activity: Oldest first"
|
||||
},
|
||||
"sort_on_created_at": {
|
||||
"TEXT": "تم إنشاؤها في"
|
||||
"last_activity_at_desc": {
|
||||
"TEXT": "Last activity: Newest first"
|
||||
},
|
||||
"sort_on_priority": {
|
||||
"TEXT": "الأولوية"
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
},
|
||||
"sort_on_waiting_since": {
|
||||
"TEXT": "Pending Response"
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
"SAVE_CONTACT": "حفظ",
|
||||
"UPLOADING_ATTACHMENTS": "جاري تحميل المرفقات...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"UNSUPPORTED_MESSAGE": "This message is unsupported.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
|
||||
"SUCCESS_DELETE_MESSAGE": "تم حذف الرسالة بنجاح",
|
||||
"FAIL_DELETE_MESSSAGE": "تعذر حذف الرسالة! حاول مرة أخرى",
|
||||
"NO_RESPONSE": "لا توجد استجابة",
|
||||
@@ -139,6 +142,7 @@
|
||||
"PRIVATE_NOTE": "إضافة ملاحظة خاصة",
|
||||
"SEND": "إرسال",
|
||||
"CREATE": "إضافة ملاحظة",
|
||||
"INSERT_READ_MORE": "Read more",
|
||||
"DISMISS_REPLY": "Dismiss reply",
|
||||
"REPLYING_TO": "Replying to:",
|
||||
"TIP_FORMAT_ICON": "عرض محرر النصوص",
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"TEXT": "قطع الاتصال من Chatwoot"
|
||||
"OFFLINE": "غير متصل"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "تحديث"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"HEADER": {
|
||||
"FILTER": "تصفية حسب",
|
||||
"SORT": "ترتيب حسب",
|
||||
"LOCALE": "اللغة",
|
||||
"SETTINGS_BUTTON": "الإعدادات",
|
||||
"NEW_BUTTON": "مقالة جديدة",
|
||||
"DROPDOWN_OPTIONS": {
|
||||
@@ -15,6 +16,12 @@
|
||||
"MINE": "مقالاتي",
|
||||
"DRAFT": "مقالات مسودة",
|
||||
"ARCHIVED": "المقالات المؤرشفة"
|
||||
},
|
||||
"LOCALE_SELECT": {
|
||||
"TITLE": "Select locale",
|
||||
"PLACEHOLDER": "Select locale",
|
||||
"NO_RESULT": "No locale found",
|
||||
"SEARCH_PLACEHOLDER": "Search locale"
|
||||
}
|
||||
},
|
||||
"EDIT_HEADER": {
|
||||
@@ -76,6 +83,9 @@
|
||||
},
|
||||
"ARTICLE_SEARCH_RESULT": {
|
||||
"UNCATEGORIZED": "Uncategorized",
|
||||
"SEARCH_RESULTS": "Search results for %{query}",
|
||||
"EMPTY_TEXT": "Search for articles to insert into replies.",
|
||||
"SEARCH_LOADER": "يبحث...",
|
||||
"INSERT_ARTICLE": "Insert",
|
||||
"NO_RESULT": "No articles found",
|
||||
"COPY_LINK": "Copy article link to clipboard",
|
||||
@@ -220,7 +230,10 @@
|
||||
"LOGO": {
|
||||
"LABEL": "Logo",
|
||||
"UPLOAD_BUTTON": "Upload logo",
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header."
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header.",
|
||||
"IMAGE_UPLOAD_SUCCESS": "Logo uploaded successfully",
|
||||
"IMAGE_UPLOAD_ERROR": "Logo deleted successfully",
|
||||
"IMAGE_DELETE_ERROR": "Error while deleting logo"
|
||||
},
|
||||
"NAME": {
|
||||
"LABEL": "الاسم",
|
||||
@@ -426,6 +439,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ARTICLE_SEARCH": {
|
||||
"TITLE": "Search articles",
|
||||
"PLACEHOLDER": "Search articles",
|
||||
"NO_RESULT": "No articles found",
|
||||
"SEARCHING": "يبحث...",
|
||||
"SEARCH_BUTTON": "بحث",
|
||||
"INSERT_ARTICLE": "Insert link",
|
||||
"IFRAME_ERROR": "URL is empty or invalid. Unable to display content.",
|
||||
"OPEN_ARTICLE_SEARCH": "Insert article from Help Center",
|
||||
"SUCCESS_ARTICLE_INSERTED": "Article inserted successfully",
|
||||
"PREVIEW_LINK": "Preview article",
|
||||
"CANCEL": "أغلق",
|
||||
"BACK": "العودة",
|
||||
"BACK_RESULTS": "Back to results"
|
||||
},
|
||||
"UPGRADE_PAGE": {
|
||||
"TITLE": "Help Center",
|
||||
"DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"FILTER": {
|
||||
"TITLE": "Филтрирай разговорите",
|
||||
"SUBTITLE": "Добавете филтри по-долу и натиснете „Прилагане на филтри“, за да филтрирате разговорите.",
|
||||
"SUBTITLE": "Add your filters below and hit 'Apply filters' to cut through the chat clutter.",
|
||||
"EDIT_CUSTOM_FILTER": "Edit Folder",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
|
||||
"ADD_NEW_FILTER": "Добавяне на филтър",
|
||||
"FILTER_DELETE_ERROR": "За да запазите, трябва да имате поне един филтър",
|
||||
"ADD_NEW_FILTER": "Add filter",
|
||||
"FILTER_DELETE_ERROR": "Oops, looks like we can't save nothing! Please add at least one filter to save it.",
|
||||
"SUBMIT_BUTTON_LABEL": "Прилагане на филтри",
|
||||
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||
"CANCEL_BUTTON_LABEL": "Отмени",
|
||||
"CLEAR_BUTTON_LABEL": "Изчисти филтрите",
|
||||
"EMPTY_VALUE_ERROR": "Изисква се стойност",
|
||||
"CLEAR_BUTTON_LABEL": "Clear filters",
|
||||
"FOLDER_LABEL": "Folder Name",
|
||||
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||
"EMPTY_VALUE_ERROR": "Изисква се стойност.",
|
||||
"TOOLTIP_LABEL": "Филтрирай разговорите",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "И",
|
||||
@@ -36,44 +36,44 @@
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"STATUS": "Статус",
|
||||
"ASSIGNEE_NAME": "Име на правоприемника",
|
||||
"INBOX_NAME": "Име на входящата кутия",
|
||||
"TEAM_NAME": "Име на екипа",
|
||||
"CONVERSATION_IDENTIFIER": "Идентивикатор на разговор",
|
||||
"CAMPAIGN_NAME": "Име на кампания",
|
||||
"ASSIGNEE_NAME": "Assignee name",
|
||||
"INBOX_NAME": "Inbox name",
|
||||
"TEAM_NAME": "Team name",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation identifier",
|
||||
"CAMPAIGN_NAME": "Campaign name",
|
||||
"LABELS": "Етикети",
|
||||
"BROWSER_LANGUAGE": "Език на браузъра",
|
||||
"BROWSER_LANGUAGE": "Browser language",
|
||||
"PRIORITY": "Priority",
|
||||
"COUNTRY_NAME": "Име на държавата",
|
||||
"COUNTRY_NAME": "Country name",
|
||||
"REFERER_LINK": "Референтна връзка",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "List",
|
||||
"CUSTOM_ATTRIBUTE_TEXT": "Text",
|
||||
"CUSTOM_ATTRIBUTE_NUMBER": "Number",
|
||||
"CUSTOM_ATTRIBUTE_LINK": "Link",
|
||||
"CUSTOM_ATTRIBUTE_CHECKBOX": "Checkbox",
|
||||
"CREATED_AT": "Created At",
|
||||
"LAST_ACTIVITY": "Последна активност"
|
||||
"CREATED_AT": "Създаден в",
|
||||
"LAST_ACTIVITY": "Last activity"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "Standard Filters",
|
||||
"ADDITIONAL_FILTERS": "Additional Filters",
|
||||
"CUSTOM_ATTRIBUTES": "Персонализирани атрибути"
|
||||
"STANDARD_FILTERS": "Standard filters",
|
||||
"ADDITIONAL_FILTERS": "Additional filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom attributes"
|
||||
},
|
||||
"CUSTOM_VIEWS": {
|
||||
"ADD": {
|
||||
"TITLE": "Do you want to save this filter?",
|
||||
"LABEL": "Name this filter",
|
||||
"PLACEHOLDER": "Enter a name for this filter",
|
||||
"ERROR_MESSAGE": "Name is required",
|
||||
"PLACEHOLDER": "Name your filter to refer it later.",
|
||||
"ERROR_MESSAGE": "Name is required.",
|
||||
"SAVE_BUTTON": "Save filter",
|
||||
"CANCEL_BUTTON": "Отмени",
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating folder"
|
||||
"SUCCESS_MESSAGE": "Folder created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating segment"
|
||||
"SUCCESS_MESSAGE": "Segment created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating segment."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
@@ -85,17 +85,17 @@
|
||||
"CONFIRM": {
|
||||
"TITLE": "Потвърди изтриването",
|
||||
"MESSAGE": "Are you sure to delete the filter ",
|
||||
"YES": "Да, изтрий",
|
||||
"NO": "No, Keep it"
|
||||
"YES": "Yes, delete",
|
||||
"NO": "No, keep it"
|
||||
}
|
||||
},
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting folder"
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting segment"
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting segment."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
{
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "Loading Editor...",
|
||||
"HEADER_BTN_TXT": "Add Bot Configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent bots allows you to automate the conversations</p>",
|
||||
"LOADING_EDITOR": "Loading editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot Name",
|
||||
"PLACEHOLDER": "Give your bot a name",
|
||||
"ERROR": "Bot name is required"
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot Description",
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above",
|
||||
"API_ERROR": "Your CSML configuration is invalid, please fix it and try again."
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "You can set an agent bot from the list to this inbox. The bot can initially handle the conversation and transfer it to an agent when needed.",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"SUBMIT": "Обновяване",
|
||||
"DISCONNECT": "Disconnect Bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot, please try again later",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot, please try again later",
|
||||
"SELECT_PLACEHOLDER": "Select Bot"
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"CANCEL_BUTTON_TEXT": "Отмени",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully",
|
||||
"ERROR_MESSAGE": "Could not add bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No Bots found, you can create a bot by clicking the 'Configure new bot' Button ↗",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TYPE": "Bot Type"
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Изтрий",
|
||||
"TITLE": "Delete Bot",
|
||||
"TITLE": "Delete bot",
|
||||
"SUBMIT": "Изтрий",
|
||||
"CANCEL_BUTTON_TEXT": "Отмени",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not able to delete bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "Редактирай",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TITLE": "Edit Bot",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"CANCEL_BUTTON_TEXT": "Отмени",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "Webhook Bot",
|
||||
"CSML": "CSML Bot"
|
||||
"WEBHOOK": "Webhook bot",
|
||||
"CSML": "CSML bot"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
{
|
||||
"BULK_ACTION": {
|
||||
"CONVERSATIONS_SELECTED": "%{conversationCount} conversations selected",
|
||||
"AGENT_SELECT_LABEL": "Select Agent",
|
||||
"AGENT_SELECT_LABEL": "Изберете агент",
|
||||
"ASSIGN_CONFIRMATION_LABEL": "Are you sure to assign %{conversationCount} %{conversationLabel} to",
|
||||
"UNASSIGN_CONFIRMATION_LABEL": "Are you sure to unassign %{conversationCount} %{conversationLabel}?",
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_LABEL": "Assign",
|
||||
"YES": "Yes",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign Agent",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations, please try again",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations, please try again",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "Conversations visible on this page are only selected.",
|
||||
"AGENT_LIST_LOADING": "Loading Agents",
|
||||
"AGENT_LIST_LOADING": "Loading agents",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "Change status",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply.",
|
||||
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
|
||||
"UPDATE_FAILED": "Failed to update conversations, please try again"
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "Assign Labels",
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"NO_LABELS_FOUND": "No labels found for",
|
||||
"ASSIGN_SELECTED_LABELS": "Assign selected labels",
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign labels, please try again"
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "Select Team",
|
||||
"TEAM_SELECT_LABEL": "Изберете екип",
|
||||
"NONE": "Нито един",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign team, please try again"
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Готови отговори",
|
||||
"HEADER_BTN_TXT": "Добавяне на готов отговор",
|
||||
"LOADING": "Извличане на готови отговори",
|
||||
"SEARCH_404": "Няма резултати отговарящи на тази заявка",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are saved reply templates which can be used to quickly send out a reply to a conversation. </p><p> For creating a Canned Response, just click on the <b>Add Canned Response</b>. You can also edit or delete an existing Canned Response by clicking on the Edit or Delete button </p><p> Canned responses are used with the help of <b>Short Codes</b>. Agents can access canned responses while on a chat by typing <b>'/'</b> followed by the short code. </p>",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"SEARCH_404": "Няма резултати отговарящи на тази заявка.",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are pre-written reply templates that help you quickly respond to a conversation. To insert a canned response during a chat, agents can type a short code preceded by a '/' character. </p><p> You can manage your canned responses from this page or create new ones using the \"Add canned response\" button.</p><p>Open the <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\">Canned Responses handbook</a> in another tab for a helping hand.</p><p>Also, check out the all-new <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">Canned Responses Library</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "Няма налични готови отговори в този акаунт.",
|
||||
"TITLE": "Управлявайте готовите отговори",
|
||||
"DESC": "Готовите отговори са предварително дефинирани шаблони за отговор, които могат да се изпращат бързо в чата.",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"TABLE_HEADER": [
|
||||
"Кратък код",
|
||||
"Short code",
|
||||
"Съдържание",
|
||||
"Действия"
|
||||
]
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Добавяне на готов отговор",
|
||||
"DESC": "Canned Responses are saved reply templates which can be used to quickly send out reply to conversation.",
|
||||
"TITLE": "Add canned response",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"CANCEL_BUTTON_TEXT": "Отмени",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Кратък код",
|
||||
"PLACEHOLDER": "Please enter a short code",
|
||||
"ERROR": "Краткия код е задължителен"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a short code.",
|
||||
"ERROR": "Short Code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Съдържание",
|
||||
"PLACEHOLDER": "Моля, въведете съдържание",
|
||||
"ERROR": "Съдържанието е задължително"
|
||||
"LABEL": "Съобщение",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Изпращане"
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Готовия отговор е добавен успешно",
|
||||
"SUCCESS_MESSAGE": "Canned response added successfully.",
|
||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Промени готовия отговор",
|
||||
"TITLE": "Edit canned response",
|
||||
"CANCEL_BUTTON_TEXT": "Отмени",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Кратък код",
|
||||
"PLACEHOLDER": "Моля, въведете кратък код",
|
||||
"ERROR": "Краткия код е задължителен"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a shortcode.",
|
||||
"ERROR": "Short code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Съдържание",
|
||||
"PLACEHOLDER": "Моля, въведете съдържание",
|
||||
"ERROR": "Съдържанието е задължително"
|
||||
"LABEL": "Съобщение",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Изпращане"
|
||||
},
|
||||
"BUTTON_TEXT": "Редактирай",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Готовия отговор е обновен успешно",
|
||||
"SUCCESS_MESSAGE": "Canned response is updated successfully.",
|
||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Изтрий",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Готовия отговор е изтрит успешно",
|
||||
"SUCCESS_MESSAGE": "Canned response deleted successfully.",
|
||||
"ERROR_MESSAGE": "Не можа да се свърже с Woot сървър. Моля, опитайте отново по-късно"
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Потвърди изтриването",
|
||||
"MESSAGE": "Сигурни ли сте за изтриването ",
|
||||
"YES": "Да, изтрий ",
|
||||
"NO": "Не, запази "
|
||||
"YES": "Yes, delete ",
|
||||
"NO": "No, keep "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,18 +51,30 @@
|
||||
"ACTIVE": "Last activity"
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_FILTER_ITEMS": {
|
||||
"latest": {
|
||||
"TEXT": "Last activity"
|
||||
"SORT_ORDER_ITEMS": {
|
||||
"last_activity_at_asc": {
|
||||
"TEXT": "Last activity: Oldest first"
|
||||
},
|
||||
"sort_on_created_at": {
|
||||
"TEXT": "Създаден в"
|
||||
"last_activity_at_desc": {
|
||||
"TEXT": "Last activity: Newest first"
|
||||
},
|
||||
"sort_on_priority": {
|
||||
"TEXT": "Priority"
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
},
|
||||
"sort_on_waiting_since": {
|
||||
"TEXT": "Pending Response"
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
"SAVE_CONTACT": "Save",
|
||||
"UPLOADING_ATTACHMENTS": "Uploading attachments...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"UNSUPPORTED_MESSAGE": "This message is unsupported.",
|
||||
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
|
||||
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
|
||||
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
|
||||
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
|
||||
"NO_RESPONSE": "No response",
|
||||
@@ -139,6 +142,7 @@
|
||||
"PRIVATE_NOTE": "Private Note",
|
||||
"SEND": "Send",
|
||||
"CREATE": "Add Note",
|
||||
"INSERT_READ_MORE": "Read more",
|
||||
"DISMISS_REPLY": "Dismiss reply",
|
||||
"REPLYING_TO": "Replying to:",
|
||||
"TIP_FORMAT_ICON": "Show rich text editor",
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
},
|
||||
"NETWORK": {
|
||||
"NOTIFICATION": {
|
||||
"TEXT": "Disconnected from Chatwoot"
|
||||
"OFFLINE": "Offline"
|
||||
},
|
||||
"BUTTON": {
|
||||
"REFRESH": "Refresh"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"HEADER": {
|
||||
"FILTER": "Filter by",
|
||||
"SORT": "Sort by",
|
||||
"LOCALE": "Locale",
|
||||
"SETTINGS_BUTTON": "Settings",
|
||||
"NEW_BUTTON": "New Article",
|
||||
"DROPDOWN_OPTIONS": {
|
||||
@@ -15,6 +16,12 @@
|
||||
"MINE": "My Articles",
|
||||
"DRAFT": "Draft Articles",
|
||||
"ARCHIVED": "Archived Articles"
|
||||
},
|
||||
"LOCALE_SELECT": {
|
||||
"TITLE": "Select locale",
|
||||
"PLACEHOLDER": "Select locale",
|
||||
"NO_RESULT": "No locale found",
|
||||
"SEARCH_PLACEHOLDER": "Search locale"
|
||||
}
|
||||
},
|
||||
"EDIT_HEADER": {
|
||||
@@ -76,6 +83,9 @@
|
||||
},
|
||||
"ARTICLE_SEARCH_RESULT": {
|
||||
"UNCATEGORIZED": "Uncategorized",
|
||||
"SEARCH_RESULTS": "Search results for %{query}",
|
||||
"EMPTY_TEXT": "Search for articles to insert into replies.",
|
||||
"SEARCH_LOADER": "Searching...",
|
||||
"INSERT_ARTICLE": "Insert",
|
||||
"NO_RESULT": "No articles found",
|
||||
"COPY_LINK": "Copy article link to clipboard",
|
||||
@@ -220,7 +230,10 @@
|
||||
"LOGO": {
|
||||
"LABEL": "Logo",
|
||||
"UPLOAD_BUTTON": "Upload logo",
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header."
|
||||
"HELP_TEXT": "This logo will be displayed on the portal header.",
|
||||
"IMAGE_UPLOAD_SUCCESS": "Logo uploaded successfully",
|
||||
"IMAGE_UPLOAD_ERROR": "Logo deleted successfully",
|
||||
"IMAGE_DELETE_ERROR": "Error while deleting logo"
|
||||
},
|
||||
"NAME": {
|
||||
"LABEL": "Име",
|
||||
@@ -426,6 +439,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ARTICLE_SEARCH": {
|
||||
"TITLE": "Search articles",
|
||||
"PLACEHOLDER": "Search articles",
|
||||
"NO_RESULT": "No articles found",
|
||||
"SEARCHING": "Searching...",
|
||||
"SEARCH_BUTTON": "Търсене",
|
||||
"INSERT_ARTICLE": "Insert link",
|
||||
"IFRAME_ERROR": "URL is empty or invalid. Unable to display content.",
|
||||
"OPEN_ARTICLE_SEARCH": "Insert article from Help Center",
|
||||
"SUCCESS_ARTICLE_INSERTED": "Article inserted successfully",
|
||||
"PREVIEW_LINK": "Preview article",
|
||||
"CANCEL": "Затвори",
|
||||
"BACK": "Back",
|
||||
"BACK_RESULTS": "Back to results"
|
||||
},
|
||||
"UPGRADE_PAGE": {
|
||||
"TITLE": "Help Center",
|
||||
"DESCRIPTION": "Create user-friendly self-service portals. Help your users to access the articles and get support 24/7. Upgrade your subscription to enable this feature.",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"FILTER": {
|
||||
"TITLE": "Filtre de converses",
|
||||
"SUBTITLE": "Add filters below and hit 'Apply filters' to filter conversations.",
|
||||
"SUBTITLE": "Add your filters below and hit 'Apply filters' to cut through the chat clutter.",
|
||||
"EDIT_CUSTOM_FILTER": "Edit Folder",
|
||||
"CUSTOM_VIEWS_SUBTITLE": "Add or remove filters and update your folder.",
|
||||
"ADD_NEW_FILTER": "Afegeix filtre",
|
||||
"FILTER_DELETE_ERROR": "You should have atleast one filter to save",
|
||||
"ADD_NEW_FILTER": "Add filter",
|
||||
"FILTER_DELETE_ERROR": "Oops, looks like we can't save nothing! Please add at least one filter to save it.",
|
||||
"SUBMIT_BUTTON_LABEL": "Aplicar filtres",
|
||||
"UPDATE_BUTTON_LABEL": "Update folder",
|
||||
"CANCEL_BUTTON_LABEL": "Cancel·la",
|
||||
"CLEAR_BUTTON_LABEL": "Clear Filters",
|
||||
"EMPTY_VALUE_ERROR": "El valor és necessari",
|
||||
"CLEAR_BUTTON_LABEL": "Clear filters",
|
||||
"FOLDER_LABEL": "Folder Name",
|
||||
"FOLDER_QUERY_LABEL": "Folder Query",
|
||||
"EMPTY_VALUE_ERROR": "El valor és necessari.",
|
||||
"TOOLTIP_LABEL": "Filtre de converses",
|
||||
"QUERY_DROPDOWN_LABELS": {
|
||||
"AND": "I",
|
||||
@@ -36,44 +36,44 @@
|
||||
},
|
||||
"ATTRIBUTES": {
|
||||
"STATUS": "Estat",
|
||||
"ASSIGNEE_NAME": "Assignee Name",
|
||||
"INBOX_NAME": "Nom de la safata d'entrada",
|
||||
"TEAM_NAME": "Nom de l'equip",
|
||||
"CONVERSATION_IDENTIFIER": "Identificador de la conversa",
|
||||
"CAMPAIGN_NAME": "Campaign Name",
|
||||
"ASSIGNEE_NAME": "Assignee name",
|
||||
"INBOX_NAME": "Inbox name",
|
||||
"TEAM_NAME": "Team name",
|
||||
"CONVERSATION_IDENTIFIER": "Conversation identifier",
|
||||
"CAMPAIGN_NAME": "Campaign name",
|
||||
"LABELS": "Etiquetes",
|
||||
"BROWSER_LANGUAGE": "Browser Language",
|
||||
"BROWSER_LANGUAGE": "Browser language",
|
||||
"PRIORITY": "Priority",
|
||||
"COUNTRY_NAME": "Nom del país",
|
||||
"COUNTRY_NAME": "Country name",
|
||||
"REFERER_LINK": "Referer link",
|
||||
"CUSTOM_ATTRIBUTE_LIST": "List",
|
||||
"CUSTOM_ATTRIBUTE_TEXT": "Llista",
|
||||
"CUSTOM_ATTRIBUTE_NUMBER": "Número",
|
||||
"CUSTOM_ATTRIBUTE_LINK": "Enllaç",
|
||||
"CUSTOM_ATTRIBUTE_CHECKBOX": "Checkbox",
|
||||
"CREATED_AT": "Created At",
|
||||
"LAST_ACTIVITY": "Last Activity"
|
||||
"CREATED_AT": "Created at",
|
||||
"LAST_ACTIVITY": "Last activity"
|
||||
},
|
||||
"GROUPS": {
|
||||
"STANDARD_FILTERS": "Standard Filters",
|
||||
"ADDITIONAL_FILTERS": "Additional Filters",
|
||||
"CUSTOM_ATTRIBUTES": "Atributs personalitzats"
|
||||
"STANDARD_FILTERS": "Standard filters",
|
||||
"ADDITIONAL_FILTERS": "Additional filters",
|
||||
"CUSTOM_ATTRIBUTES": "Custom attributes"
|
||||
},
|
||||
"CUSTOM_VIEWS": {
|
||||
"ADD": {
|
||||
"TITLE": "Do you want to save this filter?",
|
||||
"LABEL": "Name this filter",
|
||||
"PLACEHOLDER": "Enter a name for this filter",
|
||||
"ERROR_MESSAGE": "Name is required",
|
||||
"PLACEHOLDER": "Name your filter to refer it later.",
|
||||
"ERROR_MESSAGE": "Name is required.",
|
||||
"SAVE_BUTTON": "Save filter",
|
||||
"CANCEL_BUTTON": "Cancel·la",
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating folder"
|
||||
"SUCCESS_MESSAGE": "Folder created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment created successfully",
|
||||
"ERROR_MESSAGE": "Error while creating segment"
|
||||
"SUCCESS_MESSAGE": "Segment created successfully.",
|
||||
"ERROR_MESSAGE": "Error while creating segment."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
@@ -83,19 +83,19 @@
|
||||
"DELETE_BUTTON": "Delete filter",
|
||||
"MODAL": {
|
||||
"CONFIRM": {
|
||||
"TITLE": "Confirma l'esborrat",
|
||||
"TITLE": "Confirm deletion",
|
||||
"MESSAGE": "Are you sure to delete the filter ",
|
||||
"YES": "Si, esborra",
|
||||
"NO": "No, manten-la"
|
||||
"YES": "Yes, delete",
|
||||
"NO": "No, keep it"
|
||||
}
|
||||
},
|
||||
"API_FOLDERS": {
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting folder"
|
||||
"SUCCESS_MESSAGE": "Folder deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting folder."
|
||||
},
|
||||
"API_SEGMENTS": {
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully",
|
||||
"ERROR_MESSAGE": "Error while deleting segment"
|
||||
"SUCCESS_MESSAGE": "Segment deleted successfully.",
|
||||
"ERROR_MESSAGE": "Error while deleting segment."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
{
|
||||
"AGENT_BOTS": {
|
||||
"HEADER": "Bots",
|
||||
"LOADING_EDITOR": "Loading Editor...",
|
||||
"HEADER_BTN_TXT": "Add Bot Configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent bots allows you to automate the conversations</p>",
|
||||
"LOADING_EDITOR": "Loading editor...",
|
||||
"HEADER_BTN_TXT": "Add bot configuration",
|
||||
"SIDEBAR_TXT": "<p><b>Agent Bots</b> <p>Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try.</p> <p> You can manage your bots from this page or create new ones using the 'Add bot configuraton' button.</p> <p> Open the <a href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677497472-how-to-use-agent-bots\" target=\"blank\">Agent bots handbook</a> in another tab for a helping hand.</p>",
|
||||
"CSML_BOT_EDITOR": {
|
||||
"NAME": {
|
||||
"LABEL": "Bot Name",
|
||||
"PLACEHOLDER": "Give your bot a name",
|
||||
"ERROR": "Bot name is required"
|
||||
"LABEL": "Bot name",
|
||||
"PLACEHOLDER": "Name your bot.",
|
||||
"ERROR": "Bot name is required."
|
||||
},
|
||||
"DESCRIPTION": {
|
||||
"LABEL": "Bot Description",
|
||||
"LABEL": "Bot description",
|
||||
"PLACEHOLDER": "What does this bot do?"
|
||||
},
|
||||
"BOT_CONFIG": {
|
||||
"ERROR": "Please enter your CSML bot configuration above",
|
||||
"API_ERROR": "Your CSML configuration is invalid, please fix it and try again."
|
||||
"ERROR": "Please enter your CSML bot configuration above.",
|
||||
"API_ERROR": "Your CSML configuration is invalid. Please fix it and try again."
|
||||
},
|
||||
"SUBMIT": "Validate and save"
|
||||
},
|
||||
"BOT_CONFIGURATION": {
|
||||
"TITLE": "Select an agent bot",
|
||||
"DESC": "You can set an agent bot from the list to this inbox. The bot can initially handle the conversation and transfer it to an agent when needed.",
|
||||
"DESC": "Assign an Agent Bot to your inbox. They can handle initial conversations and transfer them to a live agent when necessary.",
|
||||
"SUBMIT": "Actualitza",
|
||||
"DISCONNECT": "Disconnect Bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot, please try again later",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot, please try again later",
|
||||
"SELECT_PLACEHOLDER": "Select Bot"
|
||||
"DISCONNECT": "Disconnect bot",
|
||||
"SUCCESS_MESSAGE": "Successfully updated the agent bot.",
|
||||
"DISCONNECTED_SUCCESS_MESSAGE": "Successfully disconnected the agent bot.",
|
||||
"ERROR_MESSAGE": "Could not update the agent bot. Please try again.",
|
||||
"DISCONNECTED_ERROR_MESSAGE": "Could not disconnect the agent bot. Please try again.",
|
||||
"SELECT_PLACEHOLDER": "Select bot"
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Configure new bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot added successfully",
|
||||
"ERROR_MESSAGE": "Could not add bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot added successfully.",
|
||||
"ERROR_MESSAGE": "Could not add bot. Please try again later."
|
||||
}
|
||||
},
|
||||
"LIST": {
|
||||
"404": "No Bots found, you can create a bot by clicking the 'Configure new bot' Button ↗",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TYPE": "Bot Type"
|
||||
"404": "No bots found. You can create a bot by clicking the 'Configure new bot' button ↗",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TYPE": "Bot type"
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Esborrar",
|
||||
"TITLE": "Delete Bot",
|
||||
"TITLE": "Delete bot",
|
||||
"SUBMIT": "Esborrar",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible",
|
||||
"DESCRIPTION": "Are you sure you want to delete this bot? This action is irreversible.",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully",
|
||||
"ERROR_MESSAGE": "Could not able to delete bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot deleted successfully.",
|
||||
"ERROR_MESSAGE": "Could not delete bot. Please try again."
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"BUTTON_TEXT": "Edita",
|
||||
"LOADING": "Fetching Bots...",
|
||||
"TITLE": "Edit Bot",
|
||||
"LOADING": "Fetching bots...",
|
||||
"TITLE": "Edit bot",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully",
|
||||
"ERROR_MESSAGE": "Could not update bot, Please try again later"
|
||||
"SUCCESS_MESSAGE": "Bot updated successfully.",
|
||||
"ERROR_MESSAGE": "Could not update bot. Please try again."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
"WEBHOOK": "Webhook Bot",
|
||||
"CSML": "CSML Bot"
|
||||
"WEBHOOK": "Webhook bot",
|
||||
"CSML": "CSML bot"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,34 +7,34 @@
|
||||
"GO_BACK_LABEL": "Go back",
|
||||
"ASSIGN_LABEL": "Assignar",
|
||||
"YES": "Si",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign Agent",
|
||||
"ASSIGN_AGENT_TOOLTIP": "Assign agent",
|
||||
"ASSIGN_TEAM_TOOLTIP": "Assign team",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations, please try again",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations, please try again",
|
||||
"ASSIGN_SUCCESFUL": "Conversations assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign conversations. Please try again.",
|
||||
"RESOLVE_SUCCESFUL": "Conversations resolved successfully.",
|
||||
"RESOLVE_FAILED": "Failed to resolve conversations. Please try again.",
|
||||
"ALL_CONVERSATIONS_SELECTED_ALERT": "Conversations visible on this page are only selected.",
|
||||
"AGENT_LIST_LOADING": "Loading Agents",
|
||||
"AGENT_LIST_LOADING": "Loading agents",
|
||||
"UPDATE": {
|
||||
"CHANGE_STATUS": "Change status",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply",
|
||||
"SNOOZE_UNTIL_NEXT_REPLY": "Snooze until next reply.",
|
||||
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
|
||||
"UPDATE_FAILED": "Failed to update conversations, please try again"
|
||||
"UPDATE_FAILED": "Failed to update conversations. Please try again."
|
||||
},
|
||||
"LABELS": {
|
||||
"ASSIGN_LABELS": "Assign Labels",
|
||||
"ASSIGN_LABELS": "Assign labels",
|
||||
"NO_LABELS_FOUND": "No labels found for",
|
||||
"ASSIGN_SELECTED_LABELS": "Assign selected labels",
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign labels, please try again"
|
||||
"ASSIGN_SUCCESFUL": "Labels assigned successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign labels. Please try again."
|
||||
},
|
||||
"TEAMS": {
|
||||
"TEAM_SELECT_LABEL": "Select Team",
|
||||
"TEAM_SELECT_LABEL": "Selecciona equip",
|
||||
"NONE": "Ningú",
|
||||
"NO_TEAMS_AVAILABLE": "There are no teams added to this account yet.",
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully",
|
||||
"ASSIGN_FAILED": "Failed to assign team, please try again"
|
||||
"ASSIGN_SELECTED_TEAMS": "Assign selected team.",
|
||||
"ASSIGN_SUCCESFUL": "Teams assiged successfully.",
|
||||
"ASSIGN_FAILED": "Failed to assign team. Please try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
{
|
||||
"CANNED_MGMT": {
|
||||
"HEADER": "Respostes predeterminades",
|
||||
"HEADER_BTN_TXT": "Afegeix una resposta predeterminada",
|
||||
"LOADING": "S'estan recollint les respostes predeterminades",
|
||||
"SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are saved reply templates which can be used to quickly send out a reply to a conversation. </p><p> For creating a Canned Response, just click on the <b>Add Canned Response</b>. You can also edit or delete an existing Canned Response by clicking on the Edit or Delete button </p><p> Canned responses are used with the help of <b>Short Codes</b>. Agents can access canned responses while on a chat by typing <b>'/'</b> followed by the short code. </p>",
|
||||
"HEADER_BTN_TXT": "Add canned response",
|
||||
"LOADING": "Fetching canned responses...",
|
||||
"SEARCH_404": "No hi ha cap resposta que coincideixi amb aquesta consulta.",
|
||||
"SIDEBAR_TXT": "<p><b>Canned Responses</b> </p><p> Canned Responses are pre-written reply templates that help you quickly respond to a conversation. To insert a canned response during a chat, agents can type a short code preceded by a '/' character. </p><p> You can manage your canned responses from this page or create new ones using the \"Add canned response\" button.</p><p>Open the <a target=\"_blank\" href=\"https://www.chatwoot.com/hc/chatwoot-user-guide-cloud-version/articles/1677501325-how-to-create-saved-reply-templates-with-canned-responses\">Canned Responses handbook</a> in another tab for a helping hand.</p><p>Also, check out the all-new <a href=\"https://www.chatwoot.com/tools/canned-responses-library\" target=\"_blank\">Canned Responses Library</a>.</p>",
|
||||
"LIST": {
|
||||
"404": "No hi ha respostes predeterminades disponibles en aquest compte.",
|
||||
"TITLE": "Gestiona les respostes predeterminades",
|
||||
"DESC": "Les respostes predeterminades són plantilles de resposta predefinides que es poden utilitzar per enviar ràpidament respostes a les converses.",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"TABLE_HEADER": [
|
||||
"Codi curt",
|
||||
"Short code",
|
||||
"Contingut",
|
||||
"Accions"
|
||||
]
|
||||
},
|
||||
"ADD": {
|
||||
"TITLE": "Afegeix Resposta Predeterminada",
|
||||
"DESC": "Canned Responses are saved reply templates which can be used to quickly send out reply to conversation.",
|
||||
"TITLE": "Add canned response",
|
||||
"DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to conversations.",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Codi curt",
|
||||
"PLACEHOLDER": "Introduïu un codi curt",
|
||||
"ERROR": "És necessari el codi curt"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a short code.",
|
||||
"ERROR": "Short Code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Contingut",
|
||||
"PLACEHOLDER": "Introduïu un contingut",
|
||||
"ERROR": "És necessari un contingut"
|
||||
"LABEL": "Missatge",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Envia"
|
||||
},
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Resposta predeterminada afegida correctament",
|
||||
"SUCCESS_MESSAGE": "Canned response added successfully.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||
}
|
||||
},
|
||||
"EDIT": {
|
||||
"TITLE": "Edita la resposta predeterminada",
|
||||
"TITLE": "Edit canned response",
|
||||
"CANCEL_BUTTON_TEXT": "Cancel·la",
|
||||
"FORM": {
|
||||
"SHORT_CODE": {
|
||||
"LABEL": "Codi curt",
|
||||
"PLACEHOLDER": "Introduïu un codi curt",
|
||||
"ERROR": "És necessari el codi curt"
|
||||
"LABEL": "Short code",
|
||||
"PLACEHOLDER": "Please enter a shortcode.",
|
||||
"ERROR": "Short code is required."
|
||||
},
|
||||
"CONTENT": {
|
||||
"LABEL": "Contingut",
|
||||
"PLACEHOLDER": "Introduïu un contingut",
|
||||
"ERROR": "És necessari un contingut"
|
||||
"LABEL": "Missatge",
|
||||
"PLACEHOLDER": "Please write the message you want to save as a template to use later.",
|
||||
"ERROR": "Message is required."
|
||||
},
|
||||
"SUBMIT": "Envia"
|
||||
},
|
||||
"BUTTON_TEXT": "Edita",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Resposta predeterminada actualitzada correctament",
|
||||
"SUCCESS_MESSAGE": "Canned response is updated successfully.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||
}
|
||||
},
|
||||
"DELETE": {
|
||||
"BUTTON_TEXT": "Esborra",
|
||||
"API": {
|
||||
"SUCCESS_MESSAGE": "Resposta predeterminada eliminada correctament",
|
||||
"SUCCESS_MESSAGE": "Canned response deleted successfully.",
|
||||
"ERROR_MESSAGE": "No s'ha pogut connectar amb el servidor Woot. Torna-ho a provar més endavant"
|
||||
},
|
||||
"CONFIRM": {
|
||||
"TITLE": "Confirma esborrat",
|
||||
"TITLE": "Confirm deletion",
|
||||
"MESSAGE": "N'estas segur ",
|
||||
"YES": "Si, esborra ",
|
||||
"NO": "No, segueix "
|
||||
"YES": "Yes, delete ",
|
||||
"NO": "No, keep "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user