Compare commits
51
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 |
@@ -74,7 +74,7 @@ jobs:
|
|||||||
name: yarn
|
name: yarn
|
||||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||||
|
|
||||||
# Store yarn / webpacker cache
|
# Store yarn cache
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: chatwoot-yarn-{{ .Environment.CACHE_VERSION }}-{{ checksum "yarn.lock" }}
|
key: chatwoot-yarn-{{ .Environment.CACHE_VERSION }}-{{ checksum "yarn.lock" }}
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -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 '/POSTGRES_HOST/ s/=.*/=localhost/' .env
|
||||||
sed -i -e '/SMTP_ADDRESS/ 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 "/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
|
sed -i -e "/DEV_SERVER_PUBLIC/ s/=.*/=https:\/\/$CODESPACE_NAME-3035.githubpreview.dev/" .env
|
||||||
# uncomment the webpacker env variable
|
# uncomment the dev server env variable
|
||||||
sed -i -e '/WEBPACKER_DEV_SERVER_PUBLIC/s/^# //' .env
|
sed -i -e '/DEV_SERVER_PUBLIC/s/^# //' .env
|
||||||
# fix the error with webpacker
|
# fix the error with dev server
|
||||||
echo 'export NODE_OPTIONS=--openssl-legacy-provider' >> ~/.zshrc
|
echo 'export NODE_OPTIONS=--openssl-legacy-provider' >> ~/.zshrc
|
||||||
|
|
||||||
# codespaces make the ports public
|
# 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
|
# if you want to use letter_opener for local emails
|
||||||
# LETTER_OPENER=true
|
# LETTER_OPENER=true
|
||||||
# meant to be used in github codespaces
|
# meant to be used in github codespaces
|
||||||
# WEBPACKER_DEV_SERVER_PUBLIC=
|
# DEV_SERVER_PUBLIC=
|
||||||
|
|
||||||
# If you want to use official mobile app,
|
# If you want to use official mobile app,
|
||||||
# the notifications would be relayed via a Chatwoot server
|
# the notifications would be relayed via a Chatwoot server
|
||||||
|
|||||||
+2
-10
@@ -7,11 +7,10 @@ module.exports = {
|
|||||||
'plugin:cypress/recommended',
|
'plugin:cypress/recommended',
|
||||||
],
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: '@babel/eslint-parser',
|
ecmaVersion: 2022,
|
||||||
ecmaVersion: 2020,
|
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
plugins: ['html', 'prettier', 'babel'],
|
plugins: ['html', 'prettier'],
|
||||||
rules: {
|
rules: {
|
||||||
'prettier/prettier': ['error'],
|
'prettier/prettier': ['error'],
|
||||||
camelcase: 'off',
|
camelcase: 'off',
|
||||||
@@ -56,13 +55,6 @@ module.exports = {
|
|||||||
'import/extensions': ['off'],
|
'import/extensions': ['off'],
|
||||||
'no-console': 'error',
|
'no-console': 'error',
|
||||||
},
|
},
|
||||||
settings: {
|
|
||||||
'import/resolver': {
|
|
||||||
webpack: {
|
|
||||||
config: 'config/webpack/resolve.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
jest: true,
|
jest: true,
|
||||||
|
|||||||
@@ -76,3 +76,11 @@ yarn-debug.log*
|
|||||||
.yarn-integrity
|
.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 Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import Multiselect from 'vue-multiselect';
|
import Multiselect from 'vue-multiselect';
|
||||||
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||||
import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
|
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';
|
import '../app/javascript/dashboard/assets/scss/storybook.scss';
|
||||||
|
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
Vue.use(WootUiKit);
|
Vue.use(WootUiKit);
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
||||||
@@ -32,7 +30,7 @@ addDecorator(() => ({
|
|||||||
template: '<story/>',
|
template: '<story/>',
|
||||||
i18n: i18nConfig,
|
i18n: i18nConfig,
|
||||||
store,
|
store,
|
||||||
beforeCreate: function() {
|
beforeCreate: function () {
|
||||||
this.$root._i18n = this.$i18n;
|
this.$root._i18n = this.$i18n;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ gem 'rack-attack', '>= 6.7.0'
|
|||||||
gem 'down'
|
gem 'down'
|
||||||
# authentication type to fetch and send mail over oauth2.0
|
# authentication type to fetch and send mail over oauth2.0
|
||||||
gem 'gmail_xoauth'
|
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
|
# Prevent CSV injection
|
||||||
gem 'csv-safe'
|
gem 'csv-safe'
|
||||||
|
|
||||||
@@ -62,7 +64,7 @@ gem 'activerecord-import'
|
|||||||
gem 'dotenv-rails'
|
gem 'dotenv-rails'
|
||||||
gem 'foreman'
|
gem 'foreman'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'webpacker'
|
gem 'vite_rails'
|
||||||
# metrics on heroku
|
# metrics on heroku
|
||||||
gem 'barnes'
|
gem 'barnes'
|
||||||
|
|
||||||
@@ -74,7 +76,7 @@ gem 'devise_token_auth'
|
|||||||
gem 'jwt'
|
gem 'jwt'
|
||||||
gem 'pundit'
|
gem 'pundit'
|
||||||
# super admin
|
# super admin
|
||||||
gem 'administrate', '>= 0.19.0'
|
gem 'administrate', '>= 0.20.1'
|
||||||
gem 'administrate-field-active_storage', '>= 1.0.1'
|
gem 'administrate-field-active_storage', '>= 1.0.1'
|
||||||
gem 'administrate-field-belongs_to_search', '>= 0.9.0'
|
gem 'administrate-field-belongs_to_search', '>= 0.9.0'
|
||||||
|
|
||||||
@@ -114,7 +116,7 @@ gem 'sentry-ruby', require: false
|
|||||||
gem 'sentry-sidekiq', '>= 5.14.0', require: false
|
gem 'sentry-sidekiq', '>= 5.14.0', require: false
|
||||||
|
|
||||||
##-- background job processing --##
|
##-- background job processing --##
|
||||||
gem 'sidekiq', '>= 7.1.3'
|
gem 'sidekiq', '>= 7.2.1'
|
||||||
# We want cron jobs
|
# We want cron jobs
|
||||||
gem 'sidekiq-cron', '>= 1.12.0'
|
gem 'sidekiq-cron', '>= 1.12.0'
|
||||||
|
|
||||||
|
|||||||
+25
-22
@@ -105,12 +105,12 @@ GEM
|
|||||||
activerecord (>= 6.0, < 7.1)
|
activerecord (>= 6.0, < 7.1)
|
||||||
addressable (2.8.4)
|
addressable (2.8.4)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
administrate (0.19.0)
|
administrate (0.20.1)
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 6.0, < 8.0)
|
||||||
actionview (>= 5.0)
|
actionview (>= 6.0, < 8.0)
|
||||||
activerecord (>= 5.0)
|
activerecord (>= 6.0, < 8.0)
|
||||||
jquery-rails (>= 4.0)
|
jquery-rails (~> 4.6.0)
|
||||||
kaminari (>= 1.0)
|
kaminari (~> 1.2.2)
|
||||||
sassc-rails (~> 2.1)
|
sassc-rails (~> 2.1)
|
||||||
selectize-rails (~> 0.6)
|
selectize-rails (~> 0.6)
|
||||||
administrate-field-active_storage (1.0.1)
|
administrate-field-active_storage (1.0.1)
|
||||||
@@ -169,7 +169,7 @@ GEM
|
|||||||
climate_control (1.2.0)
|
climate_control (1.2.0)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
commonmarker (0.23.10)
|
commonmarker (0.23.10)
|
||||||
concurrent-ruby (1.2.2)
|
concurrent-ruby (1.2.3)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.4.1)
|
||||||
crack (0.4.5)
|
crack (0.4.5)
|
||||||
rexml
|
rexml
|
||||||
@@ -216,6 +216,7 @@ GEM
|
|||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
down (5.4.0)
|
down (5.4.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
|
dry-cli (1.0.0)
|
||||||
ecma-re-validator (0.4.0)
|
ecma-re-validator (0.4.0)
|
||||||
regexp_parser (~> 2.2)
|
regexp_parser (~> 2.2)
|
||||||
elastic-apm (4.6.2)
|
elastic-apm (4.6.2)
|
||||||
@@ -461,7 +462,7 @@ GEM
|
|||||||
mini_magick (4.12.0)
|
mini_magick (4.12.0)
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
mini_portile2 (2.8.5)
|
mini_portile2 (2.8.5)
|
||||||
minitest (5.20.0)
|
minitest (5.21.2)
|
||||||
mock_redis (0.36.0)
|
mock_redis (0.36.0)
|
||||||
ruby2_keywords
|
ruby2_keywords
|
||||||
msgpack (1.7.0)
|
msgpack (1.7.0)
|
||||||
@@ -479,7 +480,7 @@ GEM
|
|||||||
net-protocol
|
net-protocol
|
||||||
net-protocol (0.2.2)
|
net-protocol (0.2.2)
|
||||||
timeout
|
timeout
|
||||||
net-smtp (0.4.0)
|
net-smtp (0.3.4)
|
||||||
net-protocol
|
net-protocol
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
newrelic-sidekiq-metrics (1.6.2)
|
newrelic-sidekiq-metrics (1.6.2)
|
||||||
@@ -570,7 +571,7 @@ GEM
|
|||||||
rack (>= 1.2.0)
|
rack (>= 1.2.0)
|
||||||
rack-protection (3.1.0)
|
rack-protection (3.1.0)
|
||||||
rack (~> 2.2, >= 2.2.4)
|
rack (~> 2.2, >= 2.2.4)
|
||||||
rack-proxy (0.7.6)
|
rack-proxy (0.7.7)
|
||||||
rack
|
rack
|
||||||
rack-test (2.1.0)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
@@ -610,7 +611,7 @@ GEM
|
|||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
redis (5.0.6)
|
redis (5.0.6)
|
||||||
redis-client (>= 0.9.0)
|
redis-client (>= 0.9.0)
|
||||||
redis-client (0.19.0)
|
redis-client (0.19.1)
|
||||||
connection_pool
|
connection_pool
|
||||||
redis-namespace (1.10.0)
|
redis-namespace (1.10.0)
|
||||||
redis (>= 4)
|
redis (>= 4)
|
||||||
@@ -708,7 +709,6 @@ GEM
|
|||||||
activerecord (>= 4)
|
activerecord (>= 4)
|
||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
selectize-rails (0.12.6)
|
selectize-rails (0.12.6)
|
||||||
semantic_range (3.0.0)
|
|
||||||
sentry-rails (5.14.0)
|
sentry-rails (5.14.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
sentry-ruby (~> 5.14.0)
|
sentry-ruby (~> 5.14.0)
|
||||||
@@ -720,11 +720,11 @@ GEM
|
|||||||
sexp_processor (4.17.0)
|
sexp_processor (4.17.0)
|
||||||
shoulda-matchers (5.3.0)
|
shoulda-matchers (5.3.0)
|
||||||
activesupport (>= 5.2.0)
|
activesupport (>= 5.2.0)
|
||||||
sidekiq (7.2.0)
|
sidekiq (7.2.1)
|
||||||
concurrent-ruby (< 2)
|
concurrent-ruby (< 2)
|
||||||
connection_pool (>= 2.3.0)
|
connection_pool (>= 2.3.0)
|
||||||
rack (>= 2.2.4)
|
rack (>= 2.2.4)
|
||||||
redis-client (>= 0.14.0)
|
redis-client (>= 0.19.0)
|
||||||
sidekiq-cron (1.12.0)
|
sidekiq-cron (1.12.0)
|
||||||
fugit (~> 1.8)
|
fugit (~> 1.8)
|
||||||
globalid (>= 1.0.1)
|
globalid (>= 1.0.1)
|
||||||
@@ -795,6 +795,13 @@ GEM
|
|||||||
activemodel (>= 3.2)
|
activemodel (>= 3.2)
|
||||||
mail (~> 2.5)
|
mail (~> 2.5)
|
||||||
version_gem (1.1.2)
|
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)
|
warden (1.2.9)
|
||||||
rack (>= 2.0.9)
|
rack (>= 2.0.9)
|
||||||
web-console (4.2.1)
|
web-console (4.2.1)
|
||||||
@@ -810,11 +817,6 @@ GEM
|
|||||||
addressable (>= 2.8.0)
|
addressable (>= 2.8.0)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff (>= 0.4.0, < 2.0.0)
|
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)
|
webrick (1.8.1)
|
||||||
websocket-driver (0.7.6)
|
websocket-driver (0.7.6)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
@@ -840,7 +842,7 @@ DEPENDENCIES
|
|||||||
active_record_query_trace
|
active_record_query_trace
|
||||||
activerecord-import
|
activerecord-import
|
||||||
acts-as-taggable-on
|
acts-as-taggable-on
|
||||||
administrate (>= 0.19.0)
|
administrate (>= 0.20.1)
|
||||||
administrate-field-active_storage (>= 1.0.1)
|
administrate-field-active_storage (>= 1.0.1)
|
||||||
administrate-field-belongs_to_search (>= 0.9.0)
|
administrate-field-belongs_to_search (>= 0.9.0)
|
||||||
annotate
|
annotate
|
||||||
@@ -903,6 +905,7 @@ DEPENDENCIES
|
|||||||
meta_request
|
meta_request
|
||||||
mock_redis
|
mock_redis
|
||||||
neighbor
|
neighbor
|
||||||
|
net-smtp (~> 0.3.4)
|
||||||
newrelic-sidekiq-metrics (>= 1.6.2)
|
newrelic-sidekiq-metrics (>= 1.6.2)
|
||||||
newrelic_rpm
|
newrelic_rpm
|
||||||
omniauth (>= 2.1.2)
|
omniauth (>= 2.1.2)
|
||||||
@@ -939,7 +942,7 @@ DEPENDENCIES
|
|||||||
sentry-ruby
|
sentry-ruby
|
||||||
sentry-sidekiq (>= 5.14.0)
|
sentry-sidekiq (>= 5.14.0)
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
sidekiq (>= 7.1.3)
|
sidekiq (>= 7.2.1)
|
||||||
sidekiq-cron (>= 1.12.0)
|
sidekiq-cron (>= 1.12.0)
|
||||||
simplecov (= 0.17.1)
|
simplecov (= 0.17.1)
|
||||||
slack-ruby-client (~> 2.2.0)
|
slack-ruby-client (~> 2.2.0)
|
||||||
@@ -956,10 +959,10 @@ DEPENDENCIES
|
|||||||
tzinfo-data
|
tzinfo-data
|
||||||
uglifier
|
uglifier
|
||||||
valid_email2
|
valid_email2
|
||||||
|
vite_rails
|
||||||
web-console (>= 4.2.1)
|
web-console (>= 4.2.1)
|
||||||
web-push
|
web-push
|
||||||
webmock
|
webmock
|
||||||
webpacker
|
|
||||||
wisper (= 2.0.0)
|
wisper (= 2.0.0)
|
||||||
working_hours
|
working_hours
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
backend: bin/rails s -p 3000
|
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
|
# https://github.com/mperham/sidekiq/issues/3090#issuecomment-389748695
|
||||||
worker: dotenv bundle exec sidekiq -C config/sidekiq.yml
|
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
|
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
|
worker: RAILS_ENV=test dotenv bundle exec sidekiq -C config/sidekiq.yml
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class ContactMergeAction
|
|||||||
merge_conversations
|
merge_conversations
|
||||||
merge_messages
|
merge_messages
|
||||||
merge_contact_inboxes
|
merge_contact_inboxes
|
||||||
|
merge_contact_notes
|
||||||
merge_and_remove_mergee_contact
|
merge_and_remove_mergee_contact
|
||||||
end
|
end
|
||||||
@base_contact
|
@base_contact
|
||||||
@@ -33,6 +34,10 @@ class ContactMergeAction
|
|||||||
Conversation.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
|
Conversation.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
|
||||||
end
|
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
|
def merge_messages
|
||||||
Message.where(sender: @mergee_contact).update(sender: @base_contact)
|
Message.where(sender: @mergee_contact).update(sender: @base_contact)
|
||||||
end
|
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-timing-function: cubic-bezier(.25, .8, .25, 1) !default;
|
||||||
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
|
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
|
||||||
|
|
||||||
// Ionicons
|
|
||||||
$ionicons-font-path: '~ionicons/fonts';
|
|
||||||
|
|
||||||
// Transitions
|
// Transitions
|
||||||
$transition-ease-in: all 0.250s ease-in;
|
$transition-ease-in: all 0.250s ease-in;
|
||||||
|
|||||||
@@ -46,6 +46,14 @@ class V2::ReportBuilder
|
|||||||
}
|
}
|
||||||
end
|
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
|
def conversation_metrics
|
||||||
if params[:type].equal?(:account)
|
if params[:type].equal?(:account)
|
||||||
live_conversations
|
live_conversations
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ class Api::V1::Accounts::CustomAttributeDefinitionsController < Api::V1::Account
|
|||||||
:attribute_display_type,
|
:attribute_display_type,
|
||||||
:attribute_key,
|
:attribute_key,
|
||||||
:attribute_model,
|
:attribute_model,
|
||||||
|
:regex_pattern,
|
||||||
|
:regex_cue,
|
||||||
attribute_values: []
|
attribute_values: []
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
|
|||||||
def index
|
def index
|
||||||
@unread_count = notification_finder.unread_count
|
@unread_count = notification_finder.unread_count
|
||||||
@notifications = notification_finder.perform
|
@notifications = notification_finder.perform
|
||||||
@count = @notifications.count
|
@count = notification_finder.count
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_all
|
def read_all
|
||||||
|
|||||||
@@ -14,7 +14,14 @@ module AccessTokenAuthHelper
|
|||||||
render_unauthorized('Invalid Access Token') && return if @access_token.blank?
|
render_unauthorized('Invalid Access Token') && return if @access_token.blank?
|
||||||
|
|
||||||
@resource = @access_token.owner
|
@resource = @access_token.owner
|
||||||
Current.user = @resource if [User, AgentBot].include?(@resource.class)
|
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
|
end
|
||||||
|
|
||||||
def validate_bot_access_token!
|
def validate_bot_access_token!
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class Public::Api::V1::Portals::BaseController < PublicController
|
class Public::Api::V1::Portals::BaseController < PublicController
|
||||||
before_action :show_plain_layout
|
before_action :show_plain_layout
|
||||||
before_action :set_color_scheme
|
before_action :set_color_scheme
|
||||||
|
before_action :set_global_config
|
||||||
around_action :set_locale
|
around_action :set_locale
|
||||||
after_action :allow_iframe_requests
|
after_action :allow_iframe_requests
|
||||||
|
|
||||||
@@ -60,4 +61,8 @@ class Public::Api::V1::Portals::BaseController < PublicController
|
|||||||
portal
|
portal
|
||||||
render 'public/api/v1/portals/error/404', status: :not_found
|
render 'public/api/v1/portals/error/404', status: :not_found
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_global_config
|
||||||
|
@global_config = GlobalConfig.get('LOGO_THUMBNAIL', 'BRAND_NAME', 'BRAND_URL')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ module Api::V1::InboxesHelper
|
|||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise StandardError, e.message
|
raise StandardError, e.message
|
||||||
ensure
|
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
|
end
|
||||||
|
|
||||||
def check_smtp_connection(channel_data, smtp)
|
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])
|
business_hours: ActiveModel::Type::Boolean.new.cast(params[:business_hours])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
).summary
|
).short_summary
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '~vue2-datepicker/scss/index';
|
@import 'vue2-datepicker/scss/index';
|
||||||
|
|
||||||
.date-picker {
|
.date-picker {
|
||||||
&.no-margin {
|
&.no-margin {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '~dashboard/assets/scss/variables';
|
@import 'dashboard/assets/scss/variables';
|
||||||
|
|
||||||
.formulate-input {
|
.formulate-input {
|
||||||
.formulate-input-errors {
|
.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;
|
@apply bg-slate-25 dark:bg-slate-800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-center {
|
|
||||||
@include flex-align(center, middle);
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom-space-fix {
|
.bottom-space-fix {
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@import '~dashboard/assets/scss/variables';
|
@import 'dashboard/assets/scss/variables';
|
||||||
@import '~widget/assets/scss/mixins';
|
@import 'widget/assets/scss/mixins';
|
||||||
|
|
||||||
$spinner-before-border-color: rgba(255, 255, 255, 0.7);
|
$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-function: cubic-bezier(0.37, 0, 0.63, 1) !default;
|
||||||
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-function !default;
|
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-function !default;
|
||||||
|
|
||||||
// Ionicons
|
|
||||||
$ionicons-font-path: '~ionicons/fonts';
|
|
||||||
|
|
||||||
// Transitions
|
// Transitions
|
||||||
$transition-ease-in: all 0.250s ease-in;
|
$transition-ease-in: all 0.250s ease-in;
|
||||||
|
|
||||||
|
|||||||
@@ -15,36 +15,13 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
@import 'mixins';
|
@import 'mixins';
|
||||||
@import 'foundation-settings';
|
|
||||||
@import 'helper-classes';
|
@import 'helper-classes';
|
||||||
@import 'formulate';
|
@import 'formulate';
|
||||||
@import 'date-picker';
|
@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 'typography';
|
||||||
@import 'layout';
|
@import 'layout';
|
||||||
@import 'animations';
|
@import 'animations';
|
||||||
@import 'foundation-custom';
|
|
||||||
@import 'rtl';
|
@import 'rtl';
|
||||||
|
|
||||||
@import 'widgets/buttons';
|
@import 'widgets/buttons';
|
||||||
@@ -52,15 +29,11 @@
|
|||||||
@import 'widgets/conversation-card';
|
@import 'widgets/conversation-card';
|
||||||
@import 'widgets/conversation-view';
|
@import 'widgets/conversation-view';
|
||||||
@import 'widgets/forms';
|
@import 'widgets/forms';
|
||||||
@import 'widgets/login';
|
|
||||||
@import 'widgets/modal';
|
@import 'widgets/modal';
|
||||||
@import 'widgets/reply-box';
|
@import 'widgets/reply-box';
|
||||||
@import 'widgets/report';
|
@import 'widgets/report';
|
||||||
@import 'widgets/search-box';
|
|
||||||
@import 'widgets/sidemenu';
|
|
||||||
@import 'widgets/snackbar';
|
@import 'widgets/snackbar';
|
||||||
@import 'widgets/states';
|
@import 'widgets/states';
|
||||||
@import 'widgets/status-bar';
|
|
||||||
@import 'widgets/tabs';
|
@import 'widgets/tabs';
|
||||||
@import 'widgets/woot-tables';
|
@import 'widgets/woot-tables';
|
||||||
|
|
||||||
@@ -69,7 +42,6 @@
|
|||||||
|
|
||||||
@import 'plugins/multiselect';
|
@import 'plugins/multiselect';
|
||||||
@import 'plugins/dropdown';
|
@import 'plugins/dropdown';
|
||||||
@import '~shared/assets/stylesheets/ionicons';
|
|
||||||
@import 'utility-helpers';
|
@import 'utility-helpers';
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
|
|||||||
@@ -10,21 +10,14 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
@import 'vue-multiselect/dist/vue-multiselect.min.css';
|
@import 'vue-multiselect/dist/vue-multiselect.min.css';
|
||||||
@import '~shared/assets/stylesheets/ionicons';
|
|
||||||
|
|
||||||
@import 'mixins';
|
@import 'mixins';
|
||||||
@import 'foundation-settings';
|
|
||||||
@import 'helper-classes';
|
@import 'helper-classes';
|
||||||
@import 'foundation-sites/scss/foundation';
|
|
||||||
|
|
||||||
@include foundation-prototype-spacing;
|
|
||||||
@include foundation-everything($flex: true);
|
|
||||||
|
|
||||||
@import 'typography';
|
@import 'typography';
|
||||||
@import 'layout';
|
@import 'layout';
|
||||||
@import 'animations';
|
@import 'animations';
|
||||||
|
|
||||||
@import 'foundation-custom';
|
|
||||||
@import 'widgets/buttons';
|
@import 'widgets/buttons';
|
||||||
@import 'widgets/forms';
|
@import 'widgets/forms';
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
.modal-mask {
|
||||||
// @include flex;
|
@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;
|
||||||
// @include flex-align(center, middle);
|
|
||||||
@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 {
|
.page-top-bar {
|
||||||
@@ -45,8 +43,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-footer {
|
.modal-footer {
|
||||||
// @include flex;
|
|
||||||
// @include flex-align($x: flex-end, $y: middle);
|
|
||||||
@apply flex justify-end items-center py-2 px-0 gap-2;
|
@apply flex justify-end items-center py-2 px-0 gap-2;
|
||||||
|
|
||||||
&.justify-content-end {
|
&.justify-content-end {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
.reply-box__top {
|
.reply-box__top {
|
||||||
.icon {
|
.icon {
|
||||||
color: $medium-gray;
|
color: var(--slate-500);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: $font-size-medium;
|
font-size: $font-size-medium;
|
||||||
margin-right: $space-small;
|
margin-right: $space-small;
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> textarea {
|
>textarea {
|
||||||
@include ghost-input();
|
@include ghost-input();
|
||||||
background: transparent;
|
background: transparent;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
.reply-box__top {
|
.reply-box__top {
|
||||||
@apply bg-yellow-100 dark:bg-yellow-800;
|
@apply bg-yellow-100 dark:bg-yellow-800;
|
||||||
|
|
||||||
> input {
|
>input {
|
||||||
@apply bg-yellow-100 dark:bg-yellow-800;
|
@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
|
||||||
.bottom-nav {
|
.bottom-nav {
|
||||||
@include flex;
|
@include flex;
|
||||||
@include space-between-column;
|
@include space-between-column;
|
||||||
@include border-normal-top;
|
@include border-normal-top;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--space-one) var(--space-normal) var(--space-one)
|
padding: var(--space-one) var(--space-normal) var(--space-one) var(--space-one);
|
||||||
var(--space-one);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@@ -519,6 +519,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
teamId() {
|
||||||
|
this.updateVirtualListProps('teamId', this.teamId);
|
||||||
|
},
|
||||||
activeTeam() {
|
activeTeam() {
|
||||||
this.resetAndFetchData();
|
this.resetAndFetchData();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<div class="flex items-center justify-between w-full">
|
<div class="flex items-center justify-between w-full">
|
||||||
<span
|
<span
|
||||||
class="attribute-name"
|
class="attribute-name"
|
||||||
:class="{ error: $v.editedValue.$error }"
|
:class="{ error: v$.editedValue.$error }"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</span>
|
</span>
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
:type="inputType"
|
:type="inputType"
|
||||||
class="input-group-field"
|
class="input-group-field"
|
||||||
autofocus="true"
|
autofocus="true"
|
||||||
:class="{ error: $v.editedValue.$error }"
|
:class="{ error: v$.editedValue.$error }"
|
||||||
@blur="$v.editedValue.$touch"
|
@blur="v$.editedValue.$touch"
|
||||||
@keyup.enter="onUpdate"
|
@keyup.enter="onUpdate"
|
||||||
/>
|
/>
|
||||||
<div class="input-group-button">
|
<div class="input-group-button">
|
||||||
@@ -122,25 +122,37 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { format, parseISO } from 'date-fns';
|
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 { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||||
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
||||||
import { isValidURL } from '../helper/URLHelper';
|
import { isValidURL } from '../helper/URLHelper';
|
||||||
|
import customAttributeMixin from '../mixins/customAttributeMixin';
|
||||||
const DATE_FORMAT = 'yyyy-MM-dd';
|
const DATE_FORMAT = 'yyyy-MM-dd';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MultiselectDropdown,
|
MultiselectDropdown,
|
||||||
},
|
},
|
||||||
|
mixins: [customAttributeMixin],
|
||||||
props: {
|
props: {
|
||||||
label: { type: String, required: true },
|
label: { type: String, required: true },
|
||||||
values: { type: Array, default: () => [] },
|
values: { type: Array, default: () => [] },
|
||||||
value: { type: [String, Number, Boolean], default: '' },
|
value: { type: [String, Number, Boolean], default: '' },
|
||||||
showActions: { type: Boolean, default: false },
|
showActions: { type: Boolean, default: false },
|
||||||
attributeType: { type: String, default: 'text' },
|
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 },
|
attributeKey: { type: String, required: true },
|
||||||
contactId: { type: Number, default: null },
|
contactId: { type: Number, default: null },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
@@ -198,12 +210,17 @@ export default {
|
|||||||
return this.isAttributeTypeLink ? 'url' : this.attributeType;
|
return this.isAttributeTypeLink ? 'url' : this.attributeType;
|
||||||
},
|
},
|
||||||
shouldShowErrorMessage() {
|
shouldShowErrorMessage() {
|
||||||
return this.$v.editedValue.$error;
|
return this.v$.editedValue.$error;
|
||||||
},
|
},
|
||||||
errorMessage() {
|
errorMessage() {
|
||||||
if (this.$v.editedValue.url) {
|
if (this.v$.editedValue.url) {
|
||||||
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_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');
|
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.REQUIRED');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -221,7 +238,15 @@ export default {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
editedValue: { required },
|
editedValue: {
|
||||||
|
required,
|
||||||
|
regexValidation: value => {
|
||||||
|
return !(
|
||||||
|
this.attributeRegex &&
|
||||||
|
!this.getRegexp(this.attributeRegex).test(value)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -259,8 +284,8 @@ export default {
|
|||||||
this.attributeType === 'date'
|
this.attributeType === 'date'
|
||||||
? parseISO(this.editedValue)
|
? parseISO(this.editedValue)
|
||||||
: this.editedValue;
|
: this.editedValue;
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isEditing = false;
|
this.isEditing = false;
|
||||||
@@ -281,11 +306,14 @@ export default {
|
|||||||
.checkbox-wrap {
|
.checkbox-wrap {
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
@apply my-0 mr-2 ml-0;
|
@apply my-0 mr-2 ml-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attribute-name {
|
.attribute-name {
|
||||||
@apply w-full text-slate-800 dark:text-slate-100;
|
@apply w-full text-slate-800 dark:text-slate-100;
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
@apply text-red-400 dark:text-red-500;
|
@apply text-red-400 dark:text-red-500;
|
||||||
}
|
}
|
||||||
@@ -302,6 +330,7 @@ export default {
|
|||||||
.value {
|
.value {
|
||||||
@apply bg-slate-50 dark:bg-slate-700 mb-0;
|
@apply bg-slate-50 dark:bg-slate-700 mb-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-button {
|
.edit-button {
|
||||||
@apply block;
|
@apply block;
|
||||||
}
|
}
|
||||||
@@ -311,10 +340,12 @@ export default {
|
|||||||
::v-deep {
|
::v-deep {
|
||||||
.selector-wrap {
|
.selector-wrap {
|
||||||
@apply m-0 top-1;
|
@apply m-0 top-1;
|
||||||
|
|
||||||
.selector-name {
|
.selector-name {
|
||||||
@apply ml-0;
|
@apply ml-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
@apply ml-0;
|
@apply ml-0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
/* eslint no-plusplus: 0 */
|
/* eslint no-plusplus: 0 */
|
||||||
import AvatarUploader from './widgets/forms/AvatarUploader.vue';
|
import AvatarUploader from './widgets/forms/AvatarUploader.vue';
|
||||||
import Bar from './widgets/chart/BarChart';
|
import Bar from './widgets/chart/BarChart';
|
||||||
import Button from './ui/WootButton';
|
import Button from './ui/WootButton.vue';
|
||||||
import Code from './Code';
|
import Code from './Code.vue';
|
||||||
import ColorPicker from './widgets/ColorPicker';
|
import ColorPicker from './widgets/ColorPicker.vue';
|
||||||
import ConfirmDeleteModal from './widgets/modal/ConfirmDeleteModal.vue';
|
import ConfirmDeleteModal from './widgets/modal/ConfirmDeleteModal.vue';
|
||||||
import ConfirmModal from './widgets/modal/ConfirmationModal.vue';
|
import ConfirmModal from './widgets/modal/ConfirmationModal.vue';
|
||||||
import ContextMenu from './ui/ContextMenu.vue';
|
import ContextMenu from './ui/ContextMenu.vue';
|
||||||
import DeleteModal from './widgets/modal/DeleteModal.vue';
|
import DeleteModal from './widgets/modal/DeleteModal.vue';
|
||||||
import DropdownItem from 'shared/components/ui/dropdown/DropdownItem';
|
import DropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||||
import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu';
|
import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||||
import FeatureToggle from './widgets/FeatureToggle';
|
import FeatureToggle from './widgets/FeatureToggle.vue';
|
||||||
import HorizontalBar from './widgets/chart/HorizontalBarChart';
|
import HorizontalBar from './widgets/chart/HorizontalBarChart';
|
||||||
import Input from './widgets/forms/Input.vue';
|
import Input from './widgets/forms/Input.vue';
|
||||||
import PhoneInput from './widgets/forms/PhoneInput.vue';
|
import PhoneInput from './widgets/forms/PhoneInput.vue';
|
||||||
import Label from './ui/Label';
|
import Label from './ui/Label.vue';
|
||||||
import LoadingState from './widgets/LoadingState';
|
import LoadingState from './widgets/LoadingState.vue';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal.vue';
|
||||||
import ModalHeader from './ModalHeader';
|
import ModalHeader from './ModalHeader.vue';
|
||||||
import ReportStatsCard from './widgets/ReportStatsCard';
|
import ReportStatsCard from './widgets/ReportStatsCard.vue';
|
||||||
import SidemenuIcon from './SidemenuIcon';
|
import SidemenuIcon from './SidemenuIcon.vue';
|
||||||
import Spinner from 'shared/components/Spinner';
|
import Spinner from 'shared/components/Spinner.vue';
|
||||||
import SubmitButton from './buttons/FormSubmitButton';
|
import SubmitButton from './buttons/FormSubmitButton.vue';
|
||||||
import Tabs from './ui/Tabs/Tabs';
|
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';
|
import Thumbnail from './widgets/Thumbnail.vue';
|
||||||
|
|
||||||
const WootUIKit = {
|
const WootUIKit = {
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
<form class="flex flex-col w-full" @submit.prevent="addAccount">
|
<form class="flex flex-col w-full" @submit.prevent="addAccount">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.accountName.$error }">
|
<label :class="{ error: v$.accountName.$error }">
|
||||||
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="accountName"
|
v-model.trim="accountName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.accountName.$touch"
|
@input="v$.accountName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.accountName.$invalid ||
|
v$.accountName.$invalid ||
|
||||||
$v.accountName.$invalid ||
|
v$.accountName.$invalid ||
|
||||||
uiFlags.isCreating
|
uiFlags.isCreating
|
||||||
"
|
"
|
||||||
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
||||||
@@ -49,9 +49,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
@@ -65,6 +66,9 @@ export default {
|
|||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
accountName: '',
|
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="bg-slate-50 dark:bg-slate-700 rounded text-xxs font-medium mx-1 py-0 px-1"
|
||||||
:class="
|
:class="
|
||||||
isCountZero
|
isCountZero
|
||||||
? `text-slate-300 dark:text-slate-700`
|
? `text-slate-300 dark:text-slate-500`
|
||||||
: `text-slate-700 dark:text-slate-50`
|
: `text-slate-700 dark:text-slate-50`
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export default {
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
name: 'WootTabs',
|
name: 'WootTabs',
|
||||||
props: {
|
props: {
|
||||||
index: {
|
index: {
|
||||||
@@ -73,19 +75,25 @@ export default {
|
|||||||
});
|
});
|
||||||
const leftButton = this.createScrollButton(createElement, 'left');
|
const leftButton = this.createScrollButton(createElement, 'left');
|
||||||
const rightButton = this.createScrollButton(createElement, 'right');
|
const rightButton = this.createScrollButton(createElement, 'right');
|
||||||
return (
|
return createElement(
|
||||||
<div
|
'div',
|
||||||
class={{
|
{
|
||||||
|
class: {
|
||||||
'tabs--container--with-border': this.border,
|
'tabs--container--with-border': this.border,
|
||||||
'tabs--container': true,
|
'tabs--container': true,
|
||||||
}}
|
},
|
||||||
>
|
},
|
||||||
{leftButton}
|
[
|
||||||
<ul class={{ tabs: true, 'tabs--with-scroll': this.hasScroll }}>
|
leftButton,
|
||||||
{Tabs}
|
createElement(
|
||||||
</ul>
|
'ul',
|
||||||
{rightButton}
|
{
|
||||||
</div>
|
class: { tabs: true, 'tabs--with-scroll': this.hasScroll },
|
||||||
|
},
|
||||||
|
Tabs
|
||||||
|
),
|
||||||
|
rightButton,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.value.$error }"
|
:class="{ error: v$.value.$error }"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.KEY_PLACEHOLDER')
|
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.KEY_PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.value.$touch"
|
@blur="v$.value.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-between gap-2 py-2 px-0 w-full">
|
<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">
|
<woot-button variant="clear" @click.prevent="onDismiss">
|
||||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }}
|
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }}
|
||||||
</woot-button>
|
</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') }}
|
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,15 +37,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import aiMixin from 'dashboard/mixins/aiMixin';
|
import aiMixin from 'dashboard/mixins/aiMixin';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||||
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [aiMixin, alertMixin, uiSettingsMixin],
|
mixins: [aiMixin, alertMixin, uiSettingsMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
value: '',
|
value: '',
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '~dashboard/assets/scss/variables';
|
@import 'dashboard/assets/scss/variables';
|
||||||
@import '~dashboard/assets/scss/mixins';
|
@import 'dashboard/assets/scss/mixins';
|
||||||
|
|
||||||
.colorpicker {
|
.colorpicker {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -705,10 +705,11 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~@chatwoot/prosemirror-schema/src/styles/base.scss';
|
@import '@chatwoot/prosemirror-schema/src/styles/base.scss';
|
||||||
|
|
||||||
.ProseMirror-menubar-wrapper {
|
.ProseMirror-menubar-wrapper {
|
||||||
@apply flex flex-col;
|
@apply flex flex-col;
|
||||||
|
|
||||||
.ProseMirror-menubar {
|
.ProseMirror-menubar {
|
||||||
min-height: var(--space-two) !important;
|
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;
|
@apply -ml-2.5 pb-0 bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-100;
|
||||||
@@ -717,6 +718,7 @@ export default {
|
|||||||
@apply bg-slate-75 dark:bg-slate-800;
|
@apply bg-slate-75 dark:bg-slate-800;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .ProseMirror {
|
> .ProseMirror {
|
||||||
@apply p-0 break-words text-slate-800 dark:text-slate-100;
|
@apply p-0 break-words text-slate-800 dark:text-slate-100;
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -41,7 +41,7 @@
|
|||||||
:show-query-operator="i !== appliedFilters.length - 1"
|
:show-query-operator="i !== appliedFilters.length - 1"
|
||||||
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
||||||
:grouped-filters="true"
|
:grouped-filters="true"
|
||||||
:v="$v.appliedFilters.$each[i]"
|
:v="v$.appliedFilters.$each[i]"
|
||||||
@resetFilter="resetFilter(i, appliedFilters[i])"
|
@resetFilter="resetFilter(i, appliedFilters[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
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 FilterInputBox from '../FilterInput/Index.vue';
|
||||||
import languages from './advancedFilterItems/languages';
|
import languages from './advancedFilterItems/languages';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
@@ -89,6 +89,7 @@ import { filterAttributeGroups } from './advancedFilterItems';
|
|||||||
import filterMixin from 'shared/mixins/filterMixin';
|
import filterMixin from 'shared/mixins/filterMixin';
|
||||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -117,6 +118,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
appliedFilters: {
|
appliedFilters: {
|
||||||
required,
|
required,
|
||||||
@@ -347,8 +351,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitFilterQuery() {
|
submitFilterQuery() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) return;
|
if (this.v$.$invalid) return;
|
||||||
this.$store.dispatch(
|
this.$store.dispatch(
|
||||||
'setConversationFilters',
|
'setConversationFilters',
|
||||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||||
|
|||||||
@@ -45,14 +45,14 @@
|
|||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="sentToOtherEmailAddress" class="w-[50%] mt-1">
|
<div v-if="sentToOtherEmailAddress" class="w-[50%] mt-1">
|
||||||
<label :class="{ error: $v.email.$error }">
|
<label :class="{ error: v$.email.$error }">
|
||||||
<input
|
<input
|
||||||
v-model.trim="email"
|
v-model.trim="email"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('EMAIL_TRANSCRIPT.FORM.EMAIL.PLACEHOLDER')"
|
: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') }}
|
{{ $t('EMAIL_TRANSCRIPT.FORM.EMAIL.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -73,8 +73,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
@@ -87,6 +89,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: '',
|
email: '',
|
||||||
@@ -108,7 +113,7 @@ export default {
|
|||||||
isFormValid() {
|
isFormValid() {
|
||||||
if (this.selectedType) {
|
if (this.selectedType) {
|
||||||
if (this.sentToOtherEmailAddress) {
|
if (this.sentToOtherEmailAddress) {
|
||||||
return !!this.email && !this.$v.email.$error;
|
return !!this.email && !this.v$.email.$error;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<li v-if="shouldRenderMessage" :id="`message${data.id}`" :class="alignBubble">
|
<li v-if="shouldRenderMessage" :id="`message${data.id}`" :class="alignBubble">
|
||||||
<div :class="wrapClass">
|
<div :class="wrapClass">
|
||||||
<div v-if="isFailed && !hasOneDayPassed" class="message-failed--alert">
|
<div
|
||||||
|
v-if="isFailed && !hasOneDayPassed && !isAnEmailInbox"
|
||||||
|
class="message-failed--alert"
|
||||||
|
>
|
||||||
<woot-button
|
<woot-button
|
||||||
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
|
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
|
||||||
size="tiny"
|
size="tiny"
|
||||||
@@ -203,6 +206,10 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
isAnEmailInbox: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
inboxSupportsReplyTo: {
|
inboxSupportsReplyTo: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
:is-a-whatsapp-channel="isAWhatsAppChannel"
|
:is-a-whatsapp-channel="isAWhatsAppChannel"
|
||||||
:is-web-widget-inbox="isAWebWidgetInbox"
|
:is-web-widget-inbox="isAWebWidgetInbox"
|
||||||
:is-a-facebook-inbox="isAFacebookInbox"
|
:is-a-facebook-inbox="isAFacebookInbox"
|
||||||
|
:is-an-email-inbox="isAnEmailChannel"
|
||||||
:is-instagram="isInstagramDM"
|
:is-instagram="isInstagramDM"
|
||||||
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
:inbox-supports-reply-to="inboxSupportsReplyTo"
|
||||||
:in-reply-to="getInReplyToMessage(message)"
|
:in-reply-to="getInReplyToMessage(message)"
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ import ReplyTopPanel from 'dashboard/components/widgets/WootWriter/ReplyTopPanel
|
|||||||
import ReplyEmailHead from './ReplyEmailHead.vue';
|
import ReplyEmailHead from './ReplyEmailHead.vue';
|
||||||
import ReplyBottomPanel from 'dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue';
|
import ReplyBottomPanel from 'dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue';
|
||||||
import ArticleSearchPopover from 'dashboard/routes/dashboard/helpcenter/components/ArticleSearch/SearchPopover.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 Banner from 'dashboard/components/ui/Banner.vue';
|
||||||
import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants';
|
import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
@@ -198,7 +198,7 @@ import {
|
|||||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||||
|
|
||||||
const EmojiInput = () => import('shared/components/emoji/EmojiInput');
|
const EmojiInput = () => import('shared/components/emoji/EmojiInput.vue');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -1208,6 +1208,7 @@ export default {
|
|||||||
@apply bg-yellow-50 dark:bg-yellow-200;
|
@apply bg-yellow-50 dark:bg-yellow-200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.send-button {
|
.send-button {
|
||||||
@apply mb-0;
|
@apply mb-0;
|
||||||
}
|
}
|
||||||
@@ -1228,6 +1229,7 @@ export default {
|
|||||||
|
|
||||||
.emoji-dialog--rtl {
|
.emoji-dialog--rtl {
|
||||||
@apply left-[unset] -right-80;
|
@apply left-[unset] -right-80;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.08));
|
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.08));
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="toEmails">
|
<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">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="input-group-field">
|
<div class="input-group-field">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.toEmailsVal.$model"
|
v-model.trim="v$.toEmailsVal.$model"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.toEmailsVal.$error }"
|
:class="{ error: v$.toEmailsVal.$error }"
|
||||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
/>
|
/>
|
||||||
@@ -17,15 +17,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group-wrap">
|
<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">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="input-group-field">
|
<div class="input-group-field">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.ccEmailsVal.$model"
|
v-model.trim="v$.ccEmailsVal.$model"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.ccEmailsVal.$error }"
|
:class="{ error: v$.ccEmailsVal.$error }"
|
||||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
/>
|
/>
|
||||||
@@ -39,20 +39,20 @@
|
|||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.ADD_BCC') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.ADD_BCC') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="$v.ccEmailsVal.$error" class="message">
|
<span v-if="v$.ccEmailsVal.$error" class="message">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.ERROR') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showBcc" class="input-group-wrap">
|
<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">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="input-group-field">
|
<div class="input-group-field">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.bccEmailsVal.$model"
|
v-model.trim="v$.bccEmailsVal.$model"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.bccEmailsVal.$error }"
|
:class="{ error: v$.bccEmailsVal.$error }"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')
|
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</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') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -137,7 +137,7 @@ export default {
|
|||||||
this.showBcc = true;
|
this.showBcc = true;
|
||||||
},
|
},
|
||||||
onBlur() {
|
onBlur() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
this.$emit('update:bccEmails', this.bccEmailsVal);
|
this.$emit('update:bccEmails', this.bccEmailsVal);
|
||||||
this.$emit('update:ccEmails', this.ccEmailsVal);
|
this.$emit('update:ccEmails', this.ccEmailsVal);
|
||||||
this.$emit('update:toEmails', this.toEmailsVal);
|
this.$emit('update:toEmails', this.toEmailsVal);
|
||||||
@@ -149,12 +149,14 @@ export default {
|
|||||||
.input-group-wrap .message {
|
.input-group-wrap .message {
|
||||||
@apply text-sm text-red-500 dark:text-red-500;
|
@apply text-sm text-red-500 dark:text-red-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group {
|
.input-group {
|
||||||
@apply border-b border-solid border-slate-75 dark:border-slate-700 my-1;
|
@apply border-b border-solid border-slate-75 dark:border-slate-700 my-1;
|
||||||
|
|
||||||
.input-group-label {
|
.input-group-label {
|
||||||
@apply border-transparent bg-transparent text-xs font-semibold pl-0;
|
@apply border-transparent bg-transparent text-xs font-semibold pl-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group-field::v-deep input {
|
.input-group-field::v-deep input {
|
||||||
@apply mb-0 border-transparent;
|
@apply mb-0 border-transparent;
|
||||||
}
|
}
|
||||||
@@ -162,6 +164,7 @@ export default {
|
|||||||
|
|
||||||
.input-group.error {
|
.input-group.error {
|
||||||
@apply border-b-red-500 dark:border-b-red-500;
|
@apply border-b-red-500 dark:border-b-red-500;
|
||||||
|
|
||||||
.input-group-label {
|
.input-group-label {
|
||||||
@apply text-red-500 dark:text-red-500;
|
@apply text-red-500 dark:text-red-500;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -45,7 +45,9 @@ const allKeysRequired = value => {
|
|||||||
const keys = Object.keys(value);
|
const keys = Object.keys(value);
|
||||||
return keys.every(key => value[key]);
|
return keys.every(key => value[key]);
|
||||||
};
|
};
|
||||||
import { requiredIf } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
|
import { requiredIf } from '@vuelidate/validators';
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
template: {
|
template: {
|
||||||
@@ -53,6 +55,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
processedParams: {
|
processedParams: {
|
||||||
requiredIfKeysPresent: requiredIf('variables'),
|
requiredIfKeysPresent: requiredIf('variables'),
|
||||||
@@ -149,9 +154,11 @@ footer {
|
|||||||
@apply ml-2.5;
|
@apply ml-2.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
@apply bg-red-100 dark:bg-red-100 rounded-md text-red-800 dark:text-red-800 p-2.5 text-center;
|
@apply bg-red-100 dark:bg-red-100 rounded-md text-red-800 dark:text-red-800 p-2.5 text-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.template-input {
|
.template-input {
|
||||||
@apply bg-slate-25 dark:bg-slate-900 text-slate-700 dark:text-slate-100;
|
@apply bg-slate-25 dark:bg-slate-900 text-slate-700 dark:text-slate-100;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '~dashboard/assets/scss/variables';
|
@import 'dashboard/assets/scss/variables';
|
||||||
|
|
||||||
.file {
|
.file {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import emailValidator from 'vuelidate/lib/validators/email';
|
import { email as emailValidator } from '@vuelidate/validators';
|
||||||
|
|
||||||
export const validEmailsByComma = value => {
|
export const validEmailsByComma = value => {
|
||||||
if (!value.length) return true;
|
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"
|
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"
|
@click="toggleCountryDropdown"
|
||||||
>
|
>
|
||||||
<h5 v-if="activeCountry.emoji" class="mb-0">
|
<h5 v-if="activeCountry" class="mb-0">
|
||||||
{{ activeCountry.emoji }}
|
{{ activeCountry.emoji }}
|
||||||
</h5>
|
</h5>
|
||||||
<fluent-icon v-else icon="globe" class="fluent-icon" size="16" />
|
<fluent-icon v-else icon="globe" class="fluent-icon" size="16" />
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.value.$error }"
|
:class="{ error: v$.value.$error }"
|
||||||
:placeholder="confirmPlaceHolderText"
|
:placeholder="confirmPlaceHolderText"
|
||||||
@blur="$v.value.$touch"
|
@blur="v$.value.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="button-wrapper">
|
<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 }}
|
{{ confirmText }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
<woot-button class="clear" @click.prevent="closeModal">
|
<woot-button class="clear" @click.prevent="closeModal">
|
||||||
@@ -23,14 +23,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import Modal from '../../Modal.vue';
|
import Modal from '../../Modal.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
show: {
|
show: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -61,6 +61,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
value: '',
|
value: '',
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ export const getCustomFields = ({ standardFields, customAttributes }) => {
|
|||||||
type: attribute.attribute_display_type,
|
type: attribute.attribute_display_type,
|
||||||
values: attribute.attribute_values,
|
values: attribute.attribute_values,
|
||||||
field_type: attribute.attribute_model,
|
field_type: attribute.attribute_model,
|
||||||
|
regex_pattern: attribute.regex_pattern,
|
||||||
|
regex_cue: attribute.regex_cue,
|
||||||
required: false,
|
required: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -44,4 +44,18 @@ export default {
|
|||||||
created_at: '2021-11-29T10:20:04.563Z',
|
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';
|
} from '../preChat';
|
||||||
import inboxFixture from './inboxFixture';
|
import inboxFixture from './inboxFixture';
|
||||||
|
|
||||||
const { customFields, customAttributes } = inboxFixture;
|
const { customFields, customAttributes, customAttributesWithRegex } =
|
||||||
|
inboxFixture;
|
||||||
describe('#Pre chat Helpers', () => {
|
describe('#Pre chat Helpers', () => {
|
||||||
describe('getPreChatFields', () => {
|
describe('getPreChatFields', () => {
|
||||||
it('should return correct pre-chat fields form options passed', () => {
|
it('should return correct pre-chat fields form options passed', () => {
|
||||||
@@ -27,7 +28,6 @@ describe('#Pre chat Helpers', () => {
|
|||||||
placeholder: 'Please enter your email address',
|
placeholder: 'Please enter your email address',
|
||||||
type: 'email',
|
type: 'email',
|
||||||
field_type: 'standard',
|
field_type: 'standard',
|
||||||
|
|
||||||
required: false,
|
required: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
@@ -71,6 +71,26 @@ describe('#Pre chat Helpers', () => {
|
|||||||
values: [],
|
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',
|
||||||
|
},
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,6 +39,17 @@
|
|||||||
"PLACEHOLDER": "Enter custom attribute key",
|
"PLACEHOLDER": "Enter custom attribute key",
|
||||||
"ERROR": "Key is required",
|
"ERROR": "Key is required",
|
||||||
"IN_VALID": "Invalid key"
|
"IN_VALID": "Invalid key"
|
||||||
|
},
|
||||||
|
"REGEX_PATTERN": {
|
||||||
|
"LABEL": "Regex Pattern",
|
||||||
|
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||||
|
},
|
||||||
|
"REGEX_CUE": {
|
||||||
|
"LABEL": "Regex Cue",
|
||||||
|
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||||
|
},
|
||||||
|
"ENABLE_REGEX": {
|
||||||
|
"LABEL": "Enable regex validation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
@@ -88,6 +99,17 @@
|
|||||||
"EMPTY_RESULT": {
|
"EMPTY_RESULT": {
|
||||||
"404": "There are no custom attributes created",
|
"404": "There are no custom attributes created",
|
||||||
"NOT_FOUND": "There are no custom attributes configured"
|
"NOT_FOUND": "There are no custom attributes configured"
|
||||||
|
},
|
||||||
|
"REGEX_PATTERN": {
|
||||||
|
"LABEL": "Regex Pattern",
|
||||||
|
"PLACEHOLDER": "Please enter custom attribute regex pattern. (Optional)"
|
||||||
|
},
|
||||||
|
"REGEX_CUE": {
|
||||||
|
"LABEL": "Regex Cue",
|
||||||
|
"PLACEHOLDER": "Please enter regex pattern hint. (Optional)"
|
||||||
|
},
|
||||||
|
"ENABLE_REGEX": {
|
||||||
|
"LABEL": "Enable regex validation"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,7 +339,8 @@
|
|||||||
},
|
},
|
||||||
"VALIDATIONS": {
|
"VALIDATIONS": {
|
||||||
"REQUIRED": "Valid value is required",
|
"REQUIRED": "Valid value is required",
|
||||||
"INVALID_URL": "Invalid URL"
|
"INVALID_URL": "Invalid URL",
|
||||||
|
"INVALID_INPUT": "Invalid Input"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MERGE_CONTACTS": {
|
"MERGE_CONTACTS": {
|
||||||
|
|||||||
@@ -324,7 +324,8 @@
|
|||||||
"LAST_EDITED": "Last edited"
|
"LAST_EDITED": "Last edited"
|
||||||
},
|
},
|
||||||
"COLUMNS": {
|
"COLUMNS": {
|
||||||
"BY": "by"
|
"BY": "by",
|
||||||
|
"AUTHOR_NOT_AVAILABLE": "Author is not available"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"EDIT_ARTICLE": {
|
"EDIT_ARTICLE": {
|
||||||
|
|||||||
@@ -569,7 +569,7 @@
|
|||||||
"UPDATE": "Update business hours settings",
|
"UPDATE": "Update business hours settings",
|
||||||
"TOGGLE_AVAILABILITY": "Enable business availability for this inbox",
|
"TOGGLE_AVAILABILITY": "Enable business availability for this inbox",
|
||||||
"UNAVAILABLE_MESSAGE_LABEL": "Unavailable message for visitors",
|
"UNAVAILABLE_MESSAGE_LABEL": "Unavailable message for visitors",
|
||||||
"TOGGLE_HELP": "Enabling business availability will show the available hours on live chat widget even if all the agents are offline. Outside available hours vistors can be warned with a message and a pre-chat form.",
|
"TOGGLE_HELP": "Enabling business availability will show the available hours on live chat widget even if all the agents are offline. Outside available hours visitors can be warned with a message and a pre-chat form.",
|
||||||
"DAY": {
|
"DAY": {
|
||||||
"ENABLE": "Enable availability for this day",
|
"ENABLE": "Enable availability for this day",
|
||||||
"UNAVAILABLE": "Unavailable",
|
"UNAVAILABLE": "Unavailable",
|
||||||
|
|||||||
@@ -126,6 +126,6 @@
|
|||||||
"NO_CONTENT": "Содержимое отсутствует",
|
"NO_CONTENT": "Содержимое отсутствует",
|
||||||
"HIDE_QUOTED_TEXT": "Скрыть цитируемый текст",
|
"HIDE_QUOTED_TEXT": "Скрыть цитируемый текст",
|
||||||
"SHOW_QUOTED_TEXT": "Показать цитируемый текст",
|
"SHOW_QUOTED_TEXT": "Показать цитируемый текст",
|
||||||
"MESSAGE_READ": "Читать"
|
"MESSAGE_READ": "Прочитано"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,8 +150,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitAutomation() {
|
submitAutomation() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) return;
|
if (this.v$.$invalid) return;
|
||||||
const automation = generateAutomationPayload(this.automation);
|
const automation = generateAutomationPayload(this.automation);
|
||||||
this.$emit('saveAutomation', automation, this.mode);
|
this.$emit('saveAutomation', automation, this.mode);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
import { required, requiredIf } from '@vuelidate/validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
automation: {
|
automation: {
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
getRegexp(regexPatternValue) {
|
||||||
|
let lastSlash = regexPatternValue.lastIndexOf('/');
|
||||||
|
return new RegExp(
|
||||||
|
regexPatternValue.slice(1, lastSlash),
|
||||||
|
regexPatternValue.slice(lastSlash + 1)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
<form class="w-full" @submit.prevent="addCustomAttribute">
|
<form class="w-full" @submit.prevent="addCustomAttribute">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeName"
|
v-model.trim="attributeName"
|
||||||
:class="{ error: $v.attributeName.$error }"
|
:class="{ error: v$.attributeName.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="attributeNameError"
|
:error="attributeNameError"
|
||||||
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
|
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.attributeName.$touch"
|
@input="v$.attributeName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeValue"
|
v-model.trim="attributeValue"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
/>
|
/>
|
||||||
<div class="flex justify-end items-center py-2 px-0 gap-2">
|
<div class="flex justify-end items-center py-2 px-0 gap-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.attributeName.$invalid || isCreating"
|
:is-disabled="v$.attributeName.$invalid || isCreating"
|
||||||
:is-loading="isCreating"
|
:is-loading="isCreating"
|
||||||
>
|
>
|
||||||
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
|
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
|
||||||
@@ -39,7 +39,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import Modal from 'dashboard/components/Modal.vue';
|
import Modal from 'dashboard/components/Modal.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -56,6 +57,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
attributeValue: '',
|
attributeValue: '',
|
||||||
@@ -70,7 +74,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
attributeNameError() {
|
attributeNameError() {
|
||||||
if (this.$v.attributeName.$error) {
|
if (this.v$.attributeName.$error) {
|
||||||
return this.$t('CUSTOM_ATTRIBUTES.FORM.NAME.ERROR');
|
return this.$t('CUSTOM_ATTRIBUTES.FORM.NAME.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mt-1 multiselect-wrap--medium"
|
class="mt-1 multiselect-wrap--medium"
|
||||||
:class="{ error: $v.parentContact.$error }"
|
:class="{ error: v$.parentContact.$error }"
|
||||||
>
|
>
|
||||||
<label class="multiselect__label">
|
<label class="multiselect__label">
|
||||||
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
|
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
||||||
</span>
|
</span>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
<span v-if="$v.parentContact.$error" class="message">
|
<span v-if="v$.parentContact.$error" class="message">
|
||||||
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,7 +115,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue';
|
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue';
|
||||||
import ContactDropdownItem from './ContactDropdownItem.vue';
|
import ContactDropdownItem from './ContactDropdownItem.vue';
|
||||||
@@ -141,6 +142,10 @@ export default {
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
|
|
||||||
validations: {
|
validations: {
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
required,
|
required,
|
||||||
@@ -165,8 +170,8 @@ export default {
|
|||||||
this.$emit('search', query);
|
this.$emit('search', query);
|
||||||
},
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('submit', this.parentContact.id);
|
this.$emit('submit', this.parentContact.id);
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '~dashboard/assets/scss/variables.scss';
|
@import 'dashboard/assets/scss/variables.scss';
|
||||||
|
|
||||||
.footer-wrap {
|
.footer-wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
+9
-4
@@ -41,7 +41,7 @@
|
|||||||
:dropdown-values="getDropdownValues(appliedFilters[i].attribute_key)"
|
:dropdown-values="getDropdownValues(appliedFilters[i].attribute_key)"
|
||||||
:show-query-operator="i !== appliedFilters.length - 1"
|
:show-query-operator="i !== appliedFilters.length - 1"
|
||||||
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
||||||
:v="$v.appliedFilters.$each[i]"
|
:v="v$.appliedFilters.$each[i]"
|
||||||
@resetFilter="resetFilter(i, appliedFilters[i])"
|
@resetFilter="resetFilter(i, appliedFilters[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import FilterInputBox from '../../../../components/widgets/FilterInput/Index.vue';
|
import FilterInputBox from '../../../../components/widgets/FilterInput/Index.vue';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
@@ -98,6 +98,8 @@ import { filterAttributeGroups } from '../contactFilterItems';
|
|||||||
import filterMixin from 'shared/mixins/filterMixin';
|
import filterMixin from 'shared/mixins/filterMixin';
|
||||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||||
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FilterInputBox,
|
FilterInputBox,
|
||||||
@@ -125,6 +127,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
appliedFilters: {
|
appliedFilters: {
|
||||||
required,
|
required,
|
||||||
@@ -314,8 +319,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitFilterQuery() {
|
submitFilterQuery() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) return;
|
if (this.v$.$invalid) return;
|
||||||
this.$store.dispatch(
|
this.$store.dispatch(
|
||||||
'contacts/setContactFilters',
|
'contacts/setContactFilters',
|
||||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="jsx">
|
||||||
import { mixin as clickaway } from 'vue-clickaway';
|
import { mixin as clickaway } from 'vue-clickaway';
|
||||||
import { VeTable } from 'vue-easytable';
|
import { VeTable } from 'vue-easytable';
|
||||||
import { getCountryFlag } from 'dashboard/helper/flag';
|
import { getCountryFlag } from 'dashboard/helper/flag';
|
||||||
|
|||||||
@@ -18,38 +18,38 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.name.$error }">
|
<label :class="{ error: v$.name.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.NAME.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="name"
|
v-model.trim="name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.name.$touch"
|
@input="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.email.$error }">
|
<label :class="{ error: v$.email.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="email"
|
v-model.trim="email"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.EMAIL_ADDRESS.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.EMAIL_ADDRESS.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('CONTACT_FORM.FORM.EMAIL_ADDRESS.ERROR') }}
|
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.BIO.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.BIO.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.BIO.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.BIO.PLACEHOLDER')"
|
||||||
@input="$v.description.$touch"
|
@input="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
:error="isPhoneNumberNotValid"
|
:error="isPhoneNumberNotValid"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
@input="onPhoneNumberInputChange"
|
@input="onPhoneNumberInputChange"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
@setCode="setPhoneCode"
|
@setCode="setPhoneCode"
|
||||||
/>
|
/>
|
||||||
<span v-if="isPhoneNumberNotValid" class="message">
|
<span v-if="isPhoneNumberNotValid" class="message">
|
||||||
@@ -151,10 +151,11 @@ import {
|
|||||||
DuplicateContactException,
|
DuplicateContactException,
|
||||||
ExceptionWithMessage,
|
ExceptionWithMessage,
|
||||||
} from 'shared/helpers/CustomErrors';
|
} from 'shared/helpers/CustomErrors';
|
||||||
import { required, email } from 'vuelidate/lib/validators';
|
import { required, email } from '@vuelidate/validators';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
import { isPhoneNumberValid } from 'shared/helpers/Validators';
|
import { isPhoneNumberValid } from 'shared/helpers/Validators';
|
||||||
import parsePhoneNumber from 'libphonenumber-js';
|
import parsePhoneNumber from 'libphonenumber-js';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
@@ -172,6 +173,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
countries: countries,
|
countries: countries,
|
||||||
@@ -364,8 +368,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async handleSubmit() {
|
async handleSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid || this.isPhoneNumberNotValid) {
|
if (this.v$.$invalid || this.isPhoneNumberNotValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
+24
-17
@@ -13,7 +13,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
class="multiselect-wrap--small"
|
class="multiselect-wrap--small"
|
||||||
:class="{ 'has-multi-select-error': $v.targetInbox.$error }"
|
:class="{ 'has-multi-select-error': v$.targetInbox.$error }"
|
||||||
>
|
>
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model="targetInbox"
|
v-model="targetInbox"
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
<label :class="{ error: $v.targetInbox.$error }">
|
<label :class="{ error: v$.targetInbox.$error }">
|
||||||
<span v-if="$v.targetInbox.$error" class="message">
|
<span v-if="v$.targetInbox.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.INBOX.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -76,15 +76,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="isAnEmailInbox" class="w-full">
|
<div v-if="isAnEmailInbox" class="w-full">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.subject.$error }">
|
<label :class="{ error: v$.subject.$error }">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
|
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="subject"
|
v-model="subject"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.SUBJECT.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.SUBJECT.PLACEHOLDER')"
|
||||||
@input="$v.subject.$touch"
|
@input="v$.subject.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.subject.$error" class="message">
|
<span v-if="v$.subject.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -112,13 +112,13 @@
|
|||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:signature="signatureToApply"
|
:signature="signatureToApply"
|
||||||
:allow-signature="true"
|
:allow-signature="true"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@toggle-canned-menu="toggleCannedMenu"
|
@toggle-canned-menu="toggleCannedMenu"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
>
|
>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<message-signature-missing-alert
|
<message-signature-missing-alert
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</woot-message-editor>
|
</woot-message-editor>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,16 +149,16 @@
|
|||||||
@on-select-template="toggleWaTemplate"
|
@on-select-template="toggleWaTemplate"
|
||||||
@on-send="onSendWhatsAppReply"
|
@on-send="onSendWhatsAppReply"
|
||||||
/>
|
/>
|
||||||
<label v-else :class="{ error: $v.message.$error }">
|
<label v-else :class="{ error: v$.message.$error }">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.LABEL') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="min-h-[5rem]"
|
class="min-h-[5rem]"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@input="$v.message.$touch"
|
@input="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="message">
|
<span v-if="v$.message.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -240,17 +240,17 @@ import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
|||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import ReplyEmailHead from 'dashboard/components/widgets/conversation/ReplyEmailHead.vue';
|
import ReplyEmailHead from 'dashboard/components/widgets/conversation/ReplyEmailHead.vue';
|
||||||
import CannedResponse from 'dashboard/components/widgets/conversation/CannedResponse.vue';
|
import CannedResponse from 'dashboard/components/widgets/conversation/CannedResponse.vue';
|
||||||
import MessageSignatureMissingAlert from 'dashboard/components/widgets/conversation/MessageSignatureMissingAlert';
|
import MessageSignatureMissingAlert from 'dashboard/components/widgets/conversation/MessageSignatureMissingAlert.vue';
|
||||||
import InboxDropdownItem from 'dashboard/components/widgets/InboxDropdownItem.vue';
|
import InboxDropdownItem from 'dashboard/components/widgets/InboxDropdownItem.vue';
|
||||||
import WhatsappTemplates from './WhatsappTemplates.vue';
|
import WhatsappTemplates from './WhatsappTemplates.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
||||||
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
|
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
|
||||||
import { getInboxSource } from 'dashboard/helper/inbox';
|
import { getInboxSource } from 'dashboard/helper/inbox';
|
||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
import { required, requiredIf } from '@vuelidate/validators';
|
||||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||||
import FileUpload from 'vue-upload-component';
|
import FileUpload from 'vue-upload-component';
|
||||||
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview';
|
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview.vue';
|
||||||
import { ALLOWED_FILE_TYPES } from 'shared/constants/messages';
|
import { ALLOWED_FILE_TYPES } from 'shared/constants/messages';
|
||||||
import fileUploadMixin from 'dashboard/mixins/fileUploadMixin';
|
import fileUploadMixin from 'dashboard/mixins/fileUploadMixin';
|
||||||
import {
|
import {
|
||||||
@@ -258,6 +258,7 @@ import {
|
|||||||
removeSignature,
|
removeSignature,
|
||||||
} from 'dashboard/helper/editorHelper';
|
} from 'dashboard/helper/editorHelper';
|
||||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -286,6 +287,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -494,8 +498,8 @@ export default {
|
|||||||
},
|
},
|
||||||
onFormSubmit() {
|
onFormSubmit() {
|
||||||
const isFromWhatsApp = false;
|
const isFromWhatsApp = false;
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.createConversation({
|
this.createConversation({
|
||||||
@@ -571,6 +575,7 @@ export default {
|
|||||||
.file-uploads {
|
.file-uploads {
|
||||||
@apply text-start;
|
@apply text-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect-wrap--small.has-multi-select-error {
|
.multiselect-wrap--small.has-multi-select-error {
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.multiselect__tags {
|
.multiselect__tags {
|
||||||
@@ -583,9 +588,11 @@ export default {
|
|||||||
.mention--box {
|
.mention--box {
|
||||||
@apply left-0 m-auto right-0 top-auto h-fit;
|
@apply left-0 m-auto right-0 top-auto h-fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect .multiselect__content .multiselect__option span {
|
.multiselect .multiselect__content .multiselect__option span {
|
||||||
@apply inline-flex w-6 text-slate-600 dark:text-slate-400;
|
@apply inline-flex w-6 text-slate-600 dark:text-slate-400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect .multiselect__content .multiselect__option {
|
.multiselect .multiselect__content .multiselect__option {
|
||||||
@apply py-0.5 px-1;
|
@apply py-0.5 px-1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint arrow-body-style: 0 */
|
/* eslint arrow-body-style: 0 */
|
||||||
import { frontendURL } from '../../../helper/URLHelper';
|
import { frontendURL } from '../../../helper/URLHelper';
|
||||||
const ConversationView = () => import('./ConversationView');
|
const ConversationView = () => import('./ConversationView.vue');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
routes: [
|
routes: [
|
||||||
|
|||||||
+2
@@ -11,6 +11,8 @@
|
|||||||
emoji=""
|
emoji=""
|
||||||
:value="attribute.value"
|
:value="attribute.value"
|
||||||
:show-actions="true"
|
:show-actions="true"
|
||||||
|
:attribute-regex="attribute.regex_pattern"
|
||||||
|
:regex-cue="attribute.regex_cue"
|
||||||
:class="attributeClass"
|
:class="attributeClass"
|
||||||
@update="onUpdate"
|
@update="onUpdate"
|
||||||
@delete="onDelete"
|
@delete="onDelete"
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
:label="$t('FILTER.CUSTOM_VIEWS.ADD.LABEL')"
|
:label="$t('FILTER.CUSTOM_VIEWS.ADD.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:error="
|
:error="
|
||||||
$v.name.$error ? $t('FILTER.CUSTOM_VIEWS.ADD.ERROR_MESSAGE') : ''
|
v$.name.$error ? $t('FILTER.CUSTOM_VIEWS.ADD.ERROR_MESSAGE') : ''
|
||||||
"
|
"
|
||||||
:class="{ error: $v.name.$error }"
|
:class="{ error: v$.name.$error }"
|
||||||
:placeholder="$t('FILTER.CUSTOM_VIEWS.ADD.PLACEHOLDER')"
|
:placeholder="$t('FILTER.CUSTOM_VIEWS.ADD.PLACEHOLDER')"
|
||||||
@blur="$v.name.$touch"
|
@blur="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
@@ -29,9 +29,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
@@ -49,7 +50,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -59,7 +62,7 @@ export default {
|
|||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return this.$v.name.$invalid;
|
return this.v$.name.$invalid;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -75,8 +78,8 @@ export default {
|
|||||||
this.$emit('close');
|
this.$emit('close');
|
||||||
},
|
},
|
||||||
async saveCustomViews() {
|
async saveCustomViews() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="w-full" @submit.prevent="onCreate">
|
<form class="w-full" @submit.prevent="onCreate">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.selectedLocale.$error }">
|
<label :class="{ error: v$.selectedLocale.$error }">
|
||||||
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.LABEL') }}
|
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.LABEL') }}
|
||||||
<select v-model="selectedLocale">
|
<select v-model="selectedLocale">
|
||||||
<option
|
<option
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
{{ locale.name }}-{{ locale.code }}
|
{{ locale.name }}-{{ locale.code }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedLocale.$error" class="message">
|
<span v-if="v$.selectedLocale.$error" class="message">
|
||||||
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.ERROR') }}
|
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -41,9 +41,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import Modal from 'dashboard/components/Modal.vue';
|
import Modal from 'dashboard/components/Modal.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import allLocales from 'shared/constants/locales.js';
|
import allLocales from 'shared/constants/locales.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
@@ -59,6 +61,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedLocale: '',
|
selectedLocale: '',
|
||||||
@@ -94,8 +99,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onCreate() {
|
async onCreate() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const updatedLocales = this.addedLocales;
|
const updatedLocales = this.addedLocales;
|
||||||
@@ -137,6 +142,7 @@ export default {
|
|||||||
input {
|
input {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,30 @@
|
|||||||
{{ title }}
|
{{ title }}
|
||||||
</h6>
|
</h6>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="author">
|
<div class="flex gap-1 items-center">
|
||||||
<span class="by">{{ $t('HELP_CENTER.TABLE.COLUMNS.BY') }}</span>
|
<Thumbnail
|
||||||
<span class="name">{{ articleAuthorName }}</span>
|
v-if="author"
|
||||||
|
:src="author.thumbnail"
|
||||||
|
:username="author.name"
|
||||||
|
size="16px"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
v-tooltip.right="
|
||||||
|
$t('HELP_CENTER.TABLE.COLUMNS.AUTHOR_NOT_AVAILABLE')
|
||||||
|
"
|
||||||
|
class="flex items-center justify-center rounded w-4 h-4 bg-woot-100 dark:bg-woot-700"
|
||||||
|
>
|
||||||
|
<fluent-icon
|
||||||
|
icon="person"
|
||||||
|
type="filled"
|
||||||
|
size="10"
|
||||||
|
class="text-woot-300 dark:text-woot-300"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class="font-normal text-slate-500 dark:text-slate-200 text-sm">
|
||||||
|
{{ articleAuthorName }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
@@ -57,10 +78,12 @@ import timeMixin from 'dashboard/mixins/time';
|
|||||||
import portalMixin from '../mixins/portalMixin';
|
import portalMixin from '../mixins/portalMixin';
|
||||||
import { frontendURL } from 'dashboard/helper/URLHelper';
|
import { frontendURL } from 'dashboard/helper/URLHelper';
|
||||||
import EmojiOrIcon from '../../../../../shared/components/EmojiOrIcon.vue';
|
import EmojiOrIcon from '../../../../../shared/components/EmojiOrIcon.vue';
|
||||||
|
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
EmojiOrIcon,
|
EmojiOrIcon,
|
||||||
|
Thumbnail,
|
||||||
},
|
},
|
||||||
mixins: [timeMixin, portalMixin],
|
mixins: [timeMixin, portalMixin],
|
||||||
props: {
|
props: {
|
||||||
@@ -110,7 +133,7 @@ export default {
|
|||||||
}).format(this.views || 0);
|
}).format(this.views || 0);
|
||||||
},
|
},
|
||||||
articleAuthorName() {
|
articleAuthorName() {
|
||||||
return this.author.name;
|
return this.author?.name || '-';
|
||||||
},
|
},
|
||||||
labelColor() {
|
labelColor() {
|
||||||
switch (this.status) {
|
switch (this.status) {
|
||||||
@@ -189,15 +212,6 @@ export default {
|
|||||||
.article-block {
|
.article-block {
|
||||||
@apply min-w-0;
|
@apply min-w-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.author {
|
|
||||||
.by {
|
|
||||||
@apply font-normal text-slate-500 dark:text-slate-200 text-sm;
|
|
||||||
}
|
|
||||||
.name {
|
|
||||||
@apply font-normal text-slate-500 dark:text-slate-200 text-sm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div
|
<div
|
||||||
class="my-0 py-0 px-4 grid grid-cols-6 md:grid-cols-7 lg:grid-cols-8 gap-4 border-b border-slate-100 dark:border-slate-700 sticky top-16 bg-white dark:bg-slate-900"
|
class="my-0 py-0 px-4 grid grid-cols-6 z-10 md:grid-cols-7 lg:grid-cols-8 gap-4 border-b border-slate-100 dark:border-slate-700 sticky top-16 bg-white dark:bg-slate-900"
|
||||||
:class="{ draggable: onCategoryPage }"
|
:class="{ draggable: onCategoryPage }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import UpgradePage from './UpgradePage';
|
import UpgradePage from './UpgradePage.vue';
|
||||||
import { frontendURL } from '../../../../helper/URLHelper';
|
import { frontendURL } from '../../../../helper/URLHelper';
|
||||||
import Sidebar from 'dashboard/components/layout/Sidebar.vue';
|
import Sidebar from 'dashboard/components/layout/Sidebar.vue';
|
||||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||||
|
|||||||
+18
-13
@@ -42,35 +42,35 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="name"
|
v-model.trim="name"
|
||||||
:class="{ error: $v.name.$error }"
|
:class="{ error: v$.name.$error }"
|
||||||
:error="nameError"
|
:error="nameError"
|
||||||
:label="$t('HELP_CENTER.PORTAL.ADD.NAME.LABEL')"
|
:label="$t('HELP_CENTER.PORTAL.ADD.NAME.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.PORTAL.ADD.NAME.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.PORTAL.ADD.NAME.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.PORTAL.ADD.NAME.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.PORTAL.ADD.NAME.HELP_TEXT')"
|
||||||
@blur="$v.name.$touch"
|
@blur="v$.name.$touch"
|
||||||
@input="onNameChange"
|
@input="onNameChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="slug"
|
v-model.trim="slug"
|
||||||
:class="{ error: $v.slug.$error }"
|
:class="{ error: v$.slug.$error }"
|
||||||
:error="slugError"
|
:error="slugError"
|
||||||
:label="$t('HELP_CENTER.PORTAL.ADD.SLUG.LABEL')"
|
:label="$t('HELP_CENTER.PORTAL.ADD.SLUG.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.PORTAL.ADD.SLUG.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.PORTAL.ADD.SLUG.PLACEHOLDER')"
|
||||||
:help-text="domainHelpText"
|
:help-text="domainHelpText"
|
||||||
@blur="$v.slug.$touch"
|
@blur="v$.slug.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="domain"
|
v-model.trim="domain"
|
||||||
:class="{ error: $v.domain.$error }"
|
:class="{ error: v$.domain.$error }"
|
||||||
:label="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.LABEL')"
|
:label="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.PLACEHOLDER')"
|
||||||
:help-text="domainExampleHelpText"
|
:help-text="domainExampleHelpText"
|
||||||
:error="domainError"
|
:error="domainError"
|
||||||
@blur="$v.domain.$touch"
|
@blur="v$.domain.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
<div class="flex-end">
|
<div class="flex-end">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-loading="isSubmitting"
|
:is-loading="isSubmitting"
|
||||||
:is-disabled="$v.$invalid"
|
:is-disabled="v$.$invalid"
|
||||||
@click="onSubmitClick"
|
@click="onSubmitClick"
|
||||||
>
|
>
|
||||||
{{ submitButtonText }}
|
{{ submitButtonText }}
|
||||||
@@ -88,8 +88,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { isDomain } from 'shared/helpers/Validators';
|
import { isDomain } from 'shared/helpers/Validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
@@ -118,6 +119,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -144,19 +148,19 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
nameError() {
|
nameError() {
|
||||||
if (this.$v.name.$error) {
|
if (this.v$.name.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
slugError() {
|
slugError() {
|
||||||
if (this.$v.slug.$error) {
|
if (this.v$.slug.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
domainError() {
|
domainError() {
|
||||||
if (this.$v.domain.$error) {
|
if (this.v$.domain.$error) {
|
||||||
return this.$t('HELP_CENTER.PORTAL.ADD.DOMAIN.ERROR');
|
return this.$t('HELP_CENTER.PORTAL.ADD.DOMAIN.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -192,8 +196,8 @@ export default {
|
|||||||
this.slug = convertToCategorySlug(this.name);
|
this.slug = convertToCategorySlug(this.name);
|
||||||
},
|
},
|
||||||
onSubmitClick() {
|
onSubmitClick() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +255,7 @@ export default {
|
|||||||
input {
|
input {
|
||||||
@apply mb-1;
|
@apply mb-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-text {
|
.help-text {
|
||||||
@apply mb-0;
|
@apply mb-0;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-8
@@ -47,12 +47,12 @@
|
|||||||
"
|
"
|
||||||
:help-text="homepageExampleHelpText"
|
:help-text="homepageExampleHelpText"
|
||||||
:error="
|
:error="
|
||||||
$v.homePageLink.$error
|
v$.homePageLink.$error
|
||||||
? $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.ERROR')
|
? $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:class="{ error: $v.homePageLink.$error }"
|
:class="{ error: v$.homePageLink.$error }"
|
||||||
@blur="$v.homePageLink.$touch"
|
@blur="v$.homePageLink.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
<div class="flex-end">
|
<div class="flex-end">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-loading="isSubmitting"
|
:is-loading="isSubmitting"
|
||||||
:is-disabled="$v.$invalid"
|
:is-disabled="v$.$invalid"
|
||||||
@click="onSubmitClick"
|
@click="onSubmitClick"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
@@ -74,8 +74,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { url } from 'vuelidate/lib/validators';
|
import { url } from '@vuelidate/validators';
|
||||||
import { getRandomColor } from 'dashboard/helper/labelColor';
|
import { getRandomColor } from 'dashboard/helper/labelColor';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import wootConstants from 'dashboard/constants/globals';
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
@@ -83,7 +84,6 @@ import wootConstants from 'dashboard/constants/globals';
|
|||||||
const { EXAMPLE_URL } = wootConstants;
|
const { EXAMPLE_URL } = wootConstants;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
portal: {
|
portal: {
|
||||||
@@ -95,6 +95,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
color: '#000',
|
color: '#000',
|
||||||
@@ -132,8 +135,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSubmitClick() {
|
onSubmitClick() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const portal = {
|
const portal = {
|
||||||
@@ -158,9 +161,11 @@ export default {
|
|||||||
input {
|
input {
|
||||||
@apply mb-1;
|
@apply mb-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-text {
|
.help-text {
|
||||||
@apply mb-0;
|
@apply mb-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colorpicker--selected {
|
.colorpicker--selected {
|
||||||
@apply mb-0;
|
@apply mb-0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
import HelpCenterLayout from './components/HelpCenterLayout';
|
import HelpCenterLayout from './components/HelpCenterLayout.vue';
|
||||||
import { getPortalRoute } from './helpers/routeHelper';
|
import { getPortalRoute } from './helpers/routeHelper';
|
||||||
|
|
||||||
const ListAllPortals = () => import('./pages/portals/ListAllPortals');
|
const ListAllPortals = () => import('./pages/portals/ListAllPortals.vue');
|
||||||
const NewPortal = () => import('./pages/portals/NewPortal');
|
const NewPortal = () => import('./pages/portals/NewPortal.vue');
|
||||||
|
|
||||||
const EditPortal = () => import('./pages/portals/EditPortal');
|
const EditPortal = () => import('./pages/portals/EditPortal.vue');
|
||||||
const EditPortalBasic = () => import('./pages/portals/EditPortalBasic');
|
const EditPortalBasic = () => import('./pages/portals/EditPortalBasic.vue');
|
||||||
const EditPortalCustomization = () =>
|
const EditPortalCustomization = () =>
|
||||||
import('./pages/portals/EditPortalCustomization');
|
import('./pages/portals/EditPortalCustomization.vue');
|
||||||
const EditPortalLocales = () => import('./pages/portals/EditPortalLocales.vue');
|
const EditPortalLocales = () => import('./pages/portals/EditPortalLocales.vue');
|
||||||
const ShowPortal = () => import('./pages/portals/ShowPortal');
|
const ShowPortal = () => import('./pages/portals/ShowPortal.vue');
|
||||||
const PortalDetails = () => import('./pages/portals/PortalDetails');
|
const PortalDetails = () => import('./pages/portals/PortalDetails.vue');
|
||||||
const PortalCustomization = () => import('./pages/portals/PortalCustomization');
|
const PortalCustomization = () =>
|
||||||
|
import('./pages/portals/PortalCustomization.vue');
|
||||||
const PortalSettingsFinish = () =>
|
const PortalSettingsFinish = () =>
|
||||||
import('./pages/portals/PortalSettingsFinish');
|
import('./pages/portals/PortalSettingsFinish.vue');
|
||||||
|
|
||||||
const ListAllCategories = () => import('./pages/categories/ListAllCategories');
|
const ListAllCategories = () =>
|
||||||
const NewCategory = () => import('./pages/categories/NewCategory');
|
import('./pages/categories/ListAllCategories.vue');
|
||||||
const EditCategory = () => import('./pages/categories/EditCategory');
|
const NewCategory = () => import('./pages/categories/NewCategory.vue');
|
||||||
|
const EditCategory = () => import('./pages/categories/EditCategory.vue');
|
||||||
const ListCategoryArticles = () =>
|
const ListCategoryArticles = () =>
|
||||||
import('./pages/articles/ListCategoryArticles');
|
import('./pages/articles/ListCategoryArticles.vue');
|
||||||
const ListAllArticles = () => import('./pages/articles/ListAllArticles');
|
const ListAllArticles = () => import('./pages/articles/ListAllArticles.vue');
|
||||||
const DefaultPortalArticles = () =>
|
const DefaultPortalArticles = () =>
|
||||||
import('./pages/articles/DefaultPortalArticles');
|
import('./pages/articles/DefaultPortalArticles.vue');
|
||||||
const NewArticle = () => import('./pages/articles/NewArticle');
|
const NewArticle = () => import('./pages/articles/NewArticle.vue');
|
||||||
const EditArticle = () => import('./pages/articles/EditArticle');
|
const EditArticle = () => import('./pages/articles/EditArticle.vue');
|
||||||
|
|
||||||
const portalRoutes = [
|
const portalRoutes = [
|
||||||
{
|
{
|
||||||
|
|||||||
+11
-7
@@ -25,20 +25,20 @@
|
|||||||
:label="$t('HELP_CENTER.CATEGORY.ADD.NAME.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.ADD.NAME.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.NAME.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.NAME.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.ADD.NAME.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.ADD.NAME.HELP_TEXT')"
|
||||||
:has-error="$v.name.$error"
|
:has-error="v$.name.$error"
|
||||||
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
||||||
@name-change="onNameChange"
|
@name-change="onNameChange"
|
||||||
@icon-change="onClickInsertEmoji"
|
@icon-change="onClickInsertEmoji"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="slug"
|
v-model.trim="slug"
|
||||||
:class="{ error: $v.slug.$error }"
|
:class="{ error: v$.slug.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="slugError"
|
:error="slugError"
|
||||||
:label="$t('HELP_CENTER.CATEGORY.ADD.SLUG.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.ADD.SLUG.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.SLUG.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.SLUG.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
||||||
@input="$v.slug.$touch"
|
@input="v$.slug.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
||||||
@@ -68,10 +68,11 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||||
import CategoryNameIconInput from './NameEmojiInput.vue';
|
import CategoryNameIconInput from './NameEmojiInput.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { CategoryNameIconInput },
|
components: { CategoryNameIconInput },
|
||||||
@@ -94,6 +95,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -118,7 +122,7 @@ export default {
|
|||||||
: this.portalSlug;
|
: this.portalSlug;
|
||||||
},
|
},
|
||||||
slugError() {
|
slugError() {
|
||||||
if (this.$v.slug.$error) {
|
if (this.v$.slug.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -148,8 +152,8 @@ export default {
|
|||||||
description,
|
description,
|
||||||
locale,
|
locale,
|
||||||
};
|
};
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
+12
-7
@@ -25,7 +25,7 @@
|
|||||||
:label="$t('HELP_CENTER.CATEGORY.EDIT.NAME.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.EDIT.NAME.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.NAME.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.NAME.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.NAME.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.NAME.HELP_TEXT')"
|
||||||
:has-error="$v.name.$error"
|
:has-error="v$.name.$error"
|
||||||
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
||||||
:existing-name="category.name"
|
:existing-name="category.name"
|
||||||
:saved-icon="category.icon"
|
:saved-icon="category.icon"
|
||||||
@@ -34,13 +34,13 @@
|
|||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="slug"
|
v-model.trim="slug"
|
||||||
:class="{ error: $v.slug.$error }"
|
:class="{ error: v$.slug.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="slugError"
|
:error="slugError"
|
||||||
:label="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.HELP_TEXT')"
|
||||||
@input="$v.slug.$touch"
|
@input="v$.slug.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
{{ $t('HELP_CENTER.CATEGORY.EDIT.DESCRIPTION.LABEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.EDIT.DESCRIPTION.LABEL') }}
|
||||||
@@ -70,10 +70,11 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||||
import CategoryNameIconInput from './NameEmojiInput.vue';
|
import CategoryNameIconInput from './NameEmojiInput.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { CategoryNameIconInput },
|
components: { CategoryNameIconInput },
|
||||||
@@ -100,6 +101,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
id: this.category.id,
|
id: this.category.id,
|
||||||
@@ -120,7 +124,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
slugError() {
|
slugError() {
|
||||||
if (this.$v.slug.$error) {
|
if (this.v$.slug.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -159,8 +163,8 @@ export default {
|
|||||||
slug,
|
slug,
|
||||||
description,
|
description,
|
||||||
};
|
};
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -190,6 +194,7 @@ export default {
|
|||||||
.article-info {
|
.article-info {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 0 var(--space-normal);
|
margin: 0 0 var(--space-normal);
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
color: var(--s-600);
|
color: var(--s-600);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mixin as clickaway } from 'vue-clickaway';
|
import { mixin as clickaway } from 'vue-clickaway';
|
||||||
|
|
||||||
const EmojiInput = () => import('shared/components/emoji/EmojiInput');
|
const EmojiInput = () => import('shared/components/emoji/EmojiInput.vue');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { EmojiInput },
|
components: { EmojiInput },
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@
|
|||||||
<span
|
<span
|
||||||
class="mt-1 text-slate-500 dark:text-slate-400 text-xxs font-semibold flex"
|
class="mt-1 text-slate-500 dark:text-slate-400 text-xxs font-semibold flex"
|
||||||
>
|
>
|
||||||
{{ dynamicTime(notificationItem.created_at) }}
|
{{ dynamicTime(notificationItem.last_activity_at) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-2
@@ -58,7 +58,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<div class="text-right timestamp--column">
|
<div class="text-right timestamp--column">
|
||||||
<span class="notification--created-at">
|
<span class="notification--created-at">
|
||||||
{{ dynamicTime(notificationItem.created_at) }}
|
{{ dynamicTime(notificationItem.last_activity_at) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -130,7 +130,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '~dashboard/assets/scss/mixins';
|
@import 'dashboard/assets/scss/mixins';
|
||||||
|
|
||||||
.notification--title {
|
.notification--title {
|
||||||
@apply text-sm m-0 text-slate-800 dark:text-slate-100;
|
@apply text-sm m-0 text-slate-800 dark:text-slate-100;
|
||||||
|
|||||||
+1
@@ -11,6 +11,7 @@
|
|||||||
<table-footer
|
<table-footer
|
||||||
:current-page="Number(meta.currentPage)"
|
:current-page="Number(meta.currentPage)"
|
||||||
:total-count="meta.count"
|
:total-count="meta.count"
|
||||||
|
:page-size="15"
|
||||||
@page-change="onPageChange"
|
@page-change="onPageChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,19 +13,19 @@
|
|||||||
<p>{{ $t('GENERAL_SETTINGS.FORM.GENERAL_SECTION.NOTE') }}</p>
|
<p>{{ $t('GENERAL_SETTINGS.FORM.GENERAL_SECTION.NOTE') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 flex-grow-0 flex-shrink-0 flex-[50%]">
|
<div class="p-4 flex-grow-0 flex-shrink-0 flex-[50%]">
|
||||||
<label :class="{ error: $v.name.$error }">
|
<label :class="{ error: v$.name.$error }">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.NAME.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="name"
|
v-model="name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('GENERAL_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('GENERAL_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.name.$touch"
|
@blur="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.name.$error" class="message">
|
<span v-if="v$.name.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.NAME.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.locale.$error }">
|
<label :class="{ error: v$.locale.$error }">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.LABEL') }}
|
||||||
<select v-model="locale">
|
<select v-model="locale">
|
||||||
<option
|
<option
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{{ lang.name }}
|
{{ lang.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.locale.$error" class="message">
|
<span v-if="v$.locale.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
v-if="showAutoResolutionConfig"
|
v-if="showAutoResolutionConfig"
|
||||||
:class="{ error: $v.autoResolveDuration.$error }"
|
:class="{ error: v$.autoResolveDuration.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.LABEL') }}
|
||||||
<input
|
<input
|
||||||
@@ -77,9 +77,9 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.PLACEHOLDER')
|
$t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.autoResolveDuration.$touch"
|
@blur="v$.autoResolveDuration.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.autoResolveDuration.$error" class="message">
|
<span v-if="v$.autoResolveDuration.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minValue, maxValue } from 'vuelidate/lib/validators';
|
import { required, minValue, maxValue } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import configMixin from 'shared/mixins/configMixin';
|
import configMixin from 'shared/mixins/configMixin';
|
||||||
@@ -138,9 +138,13 @@ import { FEATURE_FLAGS } from '../../../../featureFlags';
|
|||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||||
import { getLanguageDirection } from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
import { getLanguageDirection } from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [accountMixin, alertMixin, configMixin, uiSettingsMixin],
|
mixins: [accountMixin, alertMixin, configMixin, uiSettingsMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
id: '',
|
id: '',
|
||||||
@@ -251,8 +255,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async updateAccount() {
|
async updateAccount() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
this.showAlert(this.$t('GENERAL_SETTINGS.FORM.ERROR'));
|
this.showAlert(this.$t('GENERAL_SETTINGS.FORM.ERROR'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -5,7 +5,7 @@
|
|||||||
<div class="h-[calc(100vh-56px)] relative">
|
<div class="h-[calc(100vh-56px)] relative">
|
||||||
<csml-monaco-editor v-model="bot.csmlContent" class="w-full h-full" />
|
<csml-monaco-editor v-model="bot.csmlContent" class="w-full h-full" />
|
||||||
<div
|
<div
|
||||||
v-if="$v.bot.csmlContent.$error"
|
v-if="v$.bot.csmlContent.$error"
|
||||||
class="bg-red-100 dark:bg-red-200 text-white dark:text-white absolute bottom-0 w-full p-2.5 flex items-center text-xs justify-center flex-shrink-0"
|
class="bg-red-100 dark:bg-red-200 text-white dark:text-white absolute bottom-0 w-full p-2.5 flex items-center text-xs justify-center flex-shrink-0"
|
||||||
>
|
>
|
||||||
<span>{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.ERROR') }}</span>
|
<span>{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.ERROR') }}</span>
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
@submit.prevent="onSubmit"
|
@submit.prevent="onSubmit"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<label :class="{ error: $v.bot.name.$error }">
|
<label :class="{ error: v$.bot.name.$error }">
|
||||||
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.LABEL') }}
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="bot.name"
|
v-model="bot.name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.PLACEHOLDER')"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.bot.name.$error" class="message">
|
<span v-if="v$.bot.name.$error" class="message">
|
||||||
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.ERROR') }}
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -50,8 +50,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import CsmlMonacoEditor from './CSMLMonacoEditor.vue';
|
import CsmlMonacoEditor from './CSMLMonacoEditor.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { CsmlMonacoEditor },
|
components: { CsmlMonacoEditor },
|
||||||
@@ -61,6 +62,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
bot: {
|
bot: {
|
||||||
name: { required },
|
name: { required },
|
||||||
@@ -78,8 +82,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('submit', {
|
this.$emit('submit', {
|
||||||
|
|||||||
@@ -11,37 +11,37 @@
|
|||||||
@submit.prevent="addAgent()"
|
@submit.prevent="addAgent()"
|
||||||
>
|
>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentName.$error }">
|
<label :class="{ error: v$.agentName.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.NAME.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentName"
|
v-model.trim="agentName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.agentName.$touch"
|
@input="v$.agentName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentType.$error }">
|
<label :class="{ error: v$.agentType.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.LABEL') }}
|
||||||
<select v-model="agentType">
|
<select v-model="agentType">
|
||||||
<option v-for="role in roles" :key="role.name" :value="role.name">
|
<option v-for="role in roles" :key="role.name" :value="role.name">
|
||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentType.$error" class="message">
|
<span v-if="v$.agentType.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.ERROR') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentEmail.$error }">
|
<label :class="{ error: v$.agentEmail.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.EMAIL.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.EMAIL.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentEmail"
|
v-model.trim="agentEmail"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')"
|
||||||
@input="$v.agentEmail.$touch"
|
@input="v$.agentEmail.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.agentEmail.$invalid ||
|
v$.agentEmail.$invalid ||
|
||||||
$v.agentName.$invalid ||
|
v$.agentName.$invalid ||
|
||||||
uiFlags.isCreating
|
uiFlags.isCreating
|
||||||
"
|
"
|
||||||
:button-text="$t('AGENT_MGMT.ADD.FORM.SUBMIT')"
|
:button-text="$t('AGENT_MGMT.ADD.FORM.SUBMIT')"
|
||||||
@@ -67,8 +67,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -77,6 +78,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
agentName: '',
|
agentName: '',
|
||||||
|
|||||||
@@ -4,33 +4,33 @@
|
|||||||
<woot-modal-header :header-title="pageTitle" />
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
<form class="w-full" @submit.prevent="editAgent()">
|
<form class="w-full" @submit.prevent="editAgent()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentName.$error }">
|
<label :class="{ error: v$.agentName.$error }">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.NAME.LABEL') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentName"
|
v-model.trim="agentName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.EDIT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.EDIT.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.agentName.$touch"
|
@input="v$.agentName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentType.$error }">
|
<label :class="{ error: v$.agentType.$error }">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.LABEL') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.LABEL') }}
|
||||||
<select v-model="agentType">
|
<select v-model="agentType">
|
||||||
<option v-for="role in roles" :key="role.name" :value="role.name">
|
<option v-for="role in roles" :key="role.name" :value="role.name">
|
||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentType.$error" class="message">
|
<span v-if="v$.agentType.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.ERROR') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentAvailability.$error }">
|
<label :class="{ error: v$.agentAvailability.$error }">
|
||||||
{{ $t('PROFILE_SETTINGS.FORM.AVAILABILITY.LABEL') }}
|
{{ $t('PROFILE_SETTINGS.FORM.AVAILABILITY.LABEL') }}
|
||||||
<select v-model="agentAvailability">
|
<select v-model="agentAvailability">
|
||||||
<option
|
<option
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentAvailability.$error" class="message">
|
<span v-if="v$.agentAvailability.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_AVAILABILITY.ERROR') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_AVAILABILITY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
<div class="w-[50%]">
|
<div class="w-[50%]">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.agentType.$invalid ||
|
v$.agentType.$invalid ||
|
||||||
$v.agentName.$invalid ||
|
v$.agentName.$invalid ||
|
||||||
uiFlags.isUpdating
|
uiFlags.isUpdating
|
||||||
"
|
"
|
||||||
:button-text="$t('AGENT_MGMT.EDIT.FORM.SUBMIT')"
|
:button-text="$t('AGENT_MGMT.EDIT.FORM.SUBMIT')"
|
||||||
@@ -77,12 +77,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
import Modal from '../../../../components/Modal.vue';
|
import Modal from '../../../../components/Modal.vue';
|
||||||
import Auth from '../../../../api/auth';
|
import Auth from '../../../../api/auth';
|
||||||
import wootConstants from 'dashboard/constants/globals';
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
const { AVAILABILITY_STATUS_KEYS } = wootConstants;
|
const { AVAILABILITY_STATUS_KEYS } = wootConstants;
|
||||||
|
|
||||||
@@ -117,6 +118,9 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
roles: [
|
roles: [
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
<form class="flex w-full" @submit.prevent="addAttributes">
|
<form class="flex w-full" @submit.prevent="addAttributes">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.attributeModel.$error }">
|
<label :class="{ error: v$.attributeModel.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.LABEL') }}
|
||||||
<select v-model="attributeModel">
|
<select v-model="attributeModel">
|
||||||
<option v-for="model in models" :key="model.id" :value="model.id">
|
<option v-for="model in models" :key="model.id" :value="model.id">
|
||||||
{{ model.option }}
|
{{ model.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeModel.$error" class="message">
|
<span v-if="v$.attributeModel.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -20,46 +20,46 @@
|
|||||||
v-model="displayName"
|
v-model="displayName"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.displayName.$error }"
|
:class="{ error: v$.displayName.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.displayName.$error
|
v$.displayName.$error
|
||||||
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="onDisplayNameChange"
|
@input="onDisplayNameChange"
|
||||||
@blur="$v.displayName.$touch"
|
@blur="v$.displayName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="attributeKey"
|
v-model="attributeKey"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.attributeKey.$error }"
|
:class="{ error: v$.attributeKey.$error }"
|
||||||
:error="$v.attributeKey.$error ? keyErrorMessage : ''"
|
:error="v$.attributeKey.$error ? keyErrorMessage : ''"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
||||||
@blur="$v.attributeKey.$touch"
|
@blur="v$.attributeKey.$touch"
|
||||||
/>
|
/>
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="description"
|
v-model="description"
|
||||||
rows="3"
|
rows="3"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.description.$touch"
|
@blur="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.description.$error" class="message">
|
<span v-if="v$.description.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.attributeType.$error }">
|
<label :class="{ error: v$.attributeType.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
||||||
<select v-model="attributeType">
|
<select v-model="attributeType">
|
||||||
<option v-for="type in types" :key="type.id" :value="type.id">
|
<option v-for="type in types" :key="type.id" :value="type.id">
|
||||||
{{ type.option }}
|
{{ type.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeType.$error" class="message">
|
<span v-if="v$.attributeType.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -86,6 +86,30 @@
|
|||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="isAttributeTypeText">
|
||||||
|
<input
|
||||||
|
v-model="regexEnabled"
|
||||||
|
type="checkbox"
|
||||||
|
@input="toggleRegexEnabled"
|
||||||
|
/>
|
||||||
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.ENABLE_REGEX.LABEL') }}
|
||||||
|
</div>
|
||||||
|
<woot-input
|
||||||
|
v-if="isAttributeTypeText && isRegexEnabled"
|
||||||
|
v-model="regexPattern"
|
||||||
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.LABEL')"
|
||||||
|
type="text"
|
||||||
|
:placeholder="
|
||||||
|
$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.PLACEHOLDER')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<woot-input
|
||||||
|
v-if="isAttributeTypeText && isRegexEnabled"
|
||||||
|
v-model="regexCue"
|
||||||
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.LABEL')"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.PLACEHOLDER')"
|
||||||
|
/>
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="isButtonDisabled"
|
:disabled="isButtonDisabled"
|
||||||
@@ -102,11 +126,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { convertToAttributeSlug } from 'dashboard/helper/commons.js';
|
import { convertToAttributeSlug } from 'dashboard/helper/commons.js';
|
||||||
import { ATTRIBUTE_MODELS, ATTRIBUTE_TYPES } from './constants';
|
import { ATTRIBUTE_MODELS, ATTRIBUTE_TYPES } from './constants';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
@@ -116,6 +141,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -124,6 +152,9 @@ export default {
|
|||||||
attributeModel: 0,
|
attributeModel: 0,
|
||||||
attributeType: 0,
|
attributeType: 0,
|
||||||
attributeKey: '',
|
attributeKey: '',
|
||||||
|
regexPattern: null,
|
||||||
|
regexCue: null,
|
||||||
|
regexEnabled: false,
|
||||||
models: ATTRIBUTE_MODELS,
|
models: ATTRIBUTE_MODELS,
|
||||||
types: ATTRIBUTE_TYPES,
|
types: ATTRIBUTE_TYPES,
|
||||||
values: [],
|
values: [],
|
||||||
@@ -148,14 +179,14 @@ export default {
|
|||||||
},
|
},
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return (
|
return (
|
||||||
this.$v.displayName.$invalid ||
|
this.v$.displayName.$invalid ||
|
||||||
this.$v.description.$invalid ||
|
this.v$.description.$invalid ||
|
||||||
this.uiFlags.isCreating ||
|
this.uiFlags.isCreating ||
|
||||||
this.isTagInputInvalid
|
this.isTagInputInvalid
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
keyErrorMessage() {
|
keyErrorMessage() {
|
||||||
if (!this.$v.attributeKey.isKey) {
|
if (!this.v$.attributeKey.isKey) {
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
||||||
}
|
}
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
||||||
@@ -163,6 +194,12 @@ export default {
|
|||||||
isAttributeTypeList() {
|
isAttributeTypeList() {
|
||||||
return this.attributeType === 6;
|
return this.attributeType === 6;
|
||||||
},
|
},
|
||||||
|
isAttributeTypeText() {
|
||||||
|
return this.attributeType === 0;
|
||||||
|
},
|
||||||
|
isRegexEnabled() {
|
||||||
|
return this.regexEnabled;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
validations: {
|
validations: {
|
||||||
@@ -201,11 +238,18 @@ export default {
|
|||||||
onDisplayNameChange() {
|
onDisplayNameChange() {
|
||||||
this.attributeKey = convertToAttributeSlug(this.displayName);
|
this.attributeKey = convertToAttributeSlug(this.displayName);
|
||||||
},
|
},
|
||||||
|
toggleRegexEnabled() {
|
||||||
|
this.regexEnabled = !this.regexEnabled;
|
||||||
|
},
|
||||||
async addAttributes() {
|
async addAttributes() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.regexEnabled) {
|
||||||
|
this.regexPattern = null;
|
||||||
|
this.regexCue = null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('attributes/create', {
|
await this.$store.dispatch('attributes/create', {
|
||||||
attribute_display_name: this.displayName,
|
attribute_display_name: this.displayName,
|
||||||
@@ -214,6 +258,10 @@ export default {
|
|||||||
attribute_display_type: this.attributeType,
|
attribute_display_type: this.attributeType,
|
||||||
attribute_key: this.attributeKey,
|
attribute_key: this.attributeKey,
|
||||||
attribute_values: this.attributeListValues,
|
attribute_values: this.attributeListValues,
|
||||||
|
regex_pattern: this.regexPattern
|
||||||
|
? new RegExp(this.regexPattern).toString()
|
||||||
|
: null,
|
||||||
|
regex_cue: this.regexCue,
|
||||||
});
|
});
|
||||||
this.alertMessage = this.$t('ATTRIBUTES_MGMT.ADD.API.SUCCESS_MESSAGE');
|
this.alertMessage = this.$t('ATTRIBUTES_MGMT.ADD.API.SUCCESS_MESSAGE');
|
||||||
this.onClose();
|
this.onClose();
|
||||||
@@ -233,13 +281,16 @@ export default {
|
|||||||
padding: 0 var(--space-small) var(--space-small) 0;
|
padding: 0 var(--space-small) var(--space-small) 0;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect--wrap {
|
.multiselect--wrap {
|
||||||
margin-bottom: var(--space-normal);
|
margin-bottom: var(--space-normal);
|
||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: var(--r-400);
|
color: var(--r-400);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
font-weight: var(--font-weight-normal);
|
font-weight: var(--font-weight-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid {
|
.invalid {
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.multiselect__tags {
|
.multiselect__tags {
|
||||||
@@ -248,13 +299,16 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.multiselect {
|
.multiselect {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect__content-wrapper {
|
.multiselect__content-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect--active .multiselect__tags {
|
.multiselect--active .multiselect__tags {
|
||||||
border-radius: var(--border-radius-normal);
|
border-radius: var(--border-radius-normal);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,46 +7,46 @@
|
|||||||
v-model.trim="displayName"
|
v-model.trim="displayName"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.displayName.$error }"
|
:class="{ error: v$.displayName.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.displayName.$error
|
v$.displayName.$error
|
||||||
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.displayName.$touch"
|
@blur="v$.displayName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeKey"
|
v-model.trim="attributeKey"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.attributeKey.$error }"
|
:class="{ error: v$.attributeKey.$error }"
|
||||||
:error="$v.attributeKey.$error ? keyErrorMessage : ''"
|
:error="v$.attributeKey.$error ? keyErrorMessage : ''"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
||||||
readonly
|
readonly
|
||||||
@blur="$v.attributeKey.$touch"
|
@blur="v$.attributeKey.$touch"
|
||||||
/>
|
/>
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
rows="5"
|
rows="5"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.description.$touch"
|
@blur="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.description.$error" class="message">
|
<span v-if="v$.description.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.attributeType.$error }">
|
<label :class="{ error: v$.attributeType.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
||||||
<select v-model="attributeType" disabled>
|
<select v-model="attributeType" disabled>
|
||||||
<option v-for="type in types" :key="type.id" :value="type.id">
|
<option v-for="type in types" :key="type.id" :value="type.id">
|
||||||
{{ type.option }}
|
{{ type.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeType.$error" class="message">
|
<span v-if="v$.attributeType.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -70,6 +70,30 @@
|
|||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LIST.ERROR') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="isAttributeTypeText">
|
||||||
|
<input
|
||||||
|
v-model="regexEnabled"
|
||||||
|
type="checkbox"
|
||||||
|
@input="toggleRegexEnabled"
|
||||||
|
/>
|
||||||
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.ENABLE_REGEX.LABEL') }}
|
||||||
|
</div>
|
||||||
|
<woot-input
|
||||||
|
v-if="isAttributeTypeText && isRegexEnabled"
|
||||||
|
v-model="regexPattern"
|
||||||
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.LABEL')"
|
||||||
|
type="text"
|
||||||
|
:placeholder="
|
||||||
|
$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_PATTERN.PLACEHOLDER')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<woot-input
|
||||||
|
v-if="isAttributeTypeText && isRegexEnabled"
|
||||||
|
v-model="regexCue"
|
||||||
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.LABEL')"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.REGEX_CUE.PLACEHOLDER')"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<woot-button :is-loading="isUpdating" :disabled="isButtonDisabled">
|
<woot-button :is-loading="isUpdating" :disabled="isButtonDisabled">
|
||||||
@@ -85,12 +109,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { ATTRIBUTE_TYPES } from './constants';
|
import { ATTRIBUTE_TYPES } from './constants';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import customAttributeMixin from '../../../../mixins/customAttributeMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
mixins: [alertMixin, customAttributeMixin],
|
||||||
mixins: [alertMixin],
|
|
||||||
props: {
|
props: {
|
||||||
selectedAttribute: {
|
selectedAttribute: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -101,11 +127,17 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
displayName: '',
|
displayName: '',
|
||||||
description: '',
|
description: '',
|
||||||
attributeType: 0,
|
attributeType: 0,
|
||||||
|
regexPattern: null,
|
||||||
|
regexCue: null,
|
||||||
|
regexEnabled: false,
|
||||||
types: ATTRIBUTE_TYPES,
|
types: ATTRIBUTE_TYPES,
|
||||||
show: true,
|
show: true,
|
||||||
attributeKey: '',
|
attributeKey: '',
|
||||||
@@ -145,13 +177,14 @@ export default {
|
|||||||
return this.values.map(item => item.name);
|
return this.values.map(item => item.name);
|
||||||
},
|
},
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return this.$v.description.$invalid || this.isMultiselectInvalid;
|
return this.v$.description.$invalid || this.isMultiselectInvalid;
|
||||||
},
|
},
|
||||||
isMultiselectInvalid() {
|
isMultiselectInvalid() {
|
||||||
return (
|
return (
|
||||||
this.isAttributeTypeList && this.isTouched && this.values.length === 0
|
this.isAttributeTypeList && this.isTouched && this.values.length === 0
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
pageTitle() {
|
pageTitle() {
|
||||||
return `${this.$t('ATTRIBUTES_MGMT.EDIT.TITLE')} - ${
|
return `${this.$t('ATTRIBUTES_MGMT.EDIT.TITLE')} - ${
|
||||||
this.selectedAttribute.attribute_display_name
|
this.selectedAttribute.attribute_display_name
|
||||||
@@ -165,7 +198,7 @@ export default {
|
|||||||
).id;
|
).id;
|
||||||
},
|
},
|
||||||
keyErrorMessage() {
|
keyErrorMessage() {
|
||||||
if (!this.$v.attributeKey.isKey) {
|
if (!this.v$.attributeKey.isKey) {
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
||||||
}
|
}
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
||||||
@@ -173,6 +206,12 @@ export default {
|
|||||||
isAttributeTypeList() {
|
isAttributeTypeList() {
|
||||||
return this.attributeType === 6;
|
return this.attributeType === 6;
|
||||||
},
|
},
|
||||||
|
isAttributeTypeText() {
|
||||||
|
return this.attributeType === 0;
|
||||||
|
},
|
||||||
|
isRegexEnabled() {
|
||||||
|
return this.regexEnabled;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setFormValues();
|
this.setFormValues();
|
||||||
@@ -189,25 +228,38 @@ export default {
|
|||||||
this.$refs.tagInput.$el.focus();
|
this.$refs.tagInput.$el.focus();
|
||||||
},
|
},
|
||||||
setFormValues() {
|
setFormValues() {
|
||||||
|
const regexPattern = this.selectedAttribute.regex_pattern
|
||||||
|
? this.getRegexp(this.selectedAttribute.regex_pattern).source
|
||||||
|
: null;
|
||||||
this.displayName = this.selectedAttribute.attribute_display_name;
|
this.displayName = this.selectedAttribute.attribute_display_name;
|
||||||
this.description = this.selectedAttribute.attribute_description;
|
this.description = this.selectedAttribute.attribute_description;
|
||||||
this.attributeType = this.selectedAttributeType;
|
this.attributeType = this.selectedAttributeType;
|
||||||
this.attributeKey = this.selectedAttribute.attribute_key;
|
this.attributeKey = this.selectedAttribute.attribute_key;
|
||||||
|
this.regexPattern = regexPattern;
|
||||||
|
this.regexCue = this.selectedAttribute.regex_cue;
|
||||||
|
this.regexEnabled = regexPattern != null;
|
||||||
this.values = this.setAttributeListValue;
|
this.values = this.setAttributeListValue;
|
||||||
},
|
},
|
||||||
async editAttributes() {
|
async editAttributes() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.regexEnabled) {
|
||||||
|
this.regexPattern = null;
|
||||||
|
this.regexCue = null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('attributes/update', {
|
await this.$store.dispatch('attributes/update', {
|
||||||
id: this.selectedAttribute.id,
|
id: this.selectedAttribute.id,
|
||||||
attribute_description: this.description,
|
attribute_description: this.description,
|
||||||
attribute_display_name: this.displayName,
|
attribute_display_name: this.displayName,
|
||||||
attribute_values: this.updatedAttributeListValues,
|
attribute_values: this.updatedAttributeListValues,
|
||||||
|
regex_pattern: this.regexPattern
|
||||||
|
? new RegExp(this.regexPattern).toString()
|
||||||
|
: null,
|
||||||
|
regex_cue: this.regexCue,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.alertMessage = this.$t('ATTRIBUTES_MGMT.EDIT.API.SUCCESS_MESSAGE');
|
this.alertMessage = this.$t('ATTRIBUTES_MGMT.EDIT.API.SUCCESS_MESSAGE');
|
||||||
this.onClose();
|
this.onClose();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -218,6 +270,9 @@ export default {
|
|||||||
this.showAlert(this.alertMessage);
|
this.showAlert(this.alertMessage);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
toggleRegexEnabled() {
|
||||||
|
this.regexEnabled = !this.regexEnabled;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -226,13 +281,16 @@ export default {
|
|||||||
padding: 0 var(--space-small) var(--space-small) 0;
|
padding: 0 var(--space-small) var(--space-small) 0;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect--wrap {
|
.multiselect--wrap {
|
||||||
margin-bottom: var(--space-normal);
|
margin-bottom: var(--space-normal);
|
||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: var(--r-400);
|
color: var(--r-400);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
font-weight: var(--font-weight-normal);
|
font-weight: var(--font-weight-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid {
|
.invalid {
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.multiselect__tags {
|
.multiselect__tags {
|
||||||
@@ -241,13 +299,16 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.multiselect {
|
.multiselect {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect__content-wrapper {
|
.multiselect__content-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect--active .multiselect__tags {
|
.multiselect--active .multiselect__tags {
|
||||||
border-radius: var(--border-radius-normal);
|
border-radius: var(--border-radius-normal);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -7,30 +7,30 @@
|
|||||||
v-model="automation.name"
|
v-model="automation.name"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.name.$error }"
|
:class="{ error: v$.automation.name.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.name.$error
|
v$.automation.name.$error
|
||||||
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.automation.name.$touch"
|
@blur="v$.automation.name.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="automation.description"
|
v-model="automation.description"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.description.$error }"
|
:class="{ error: v$.automation.description.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.description.$error
|
v$.automation.description.$error
|
||||||
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.automation.description.$touch"
|
@blur="v$.automation.description.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="event_wrapper">
|
<div class="event_wrapper">
|
||||||
<label :class="{ error: $v.automation.event_name.$error }">
|
<label :class="{ error: v$.automation.event_name.$error }">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
||||||
<select v-model="automation.event_name" @change="onEventChange()">
|
<select v-model="automation.event_name" @change="onEventChange()">
|
||||||
<option
|
<option
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
{{ event.value }}
|
{{ event.value }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.automation.event_name.$error" class="message">
|
<span v-if="v$.automation.event_name.$error" class="message">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
:custom-attribute-type="
|
:custom-attribute-type="
|
||||||
getCustomAttributeType(automation.conditions[i].attribute_key)
|
getCustomAttributeType(automation.conditions[i].attribute_key)
|
||||||
"
|
"
|
||||||
:v="$v.automation.conditions.$each[i]"
|
:v="v$.automation.conditions.$each[i]"
|
||||||
@resetFilter="resetFilter(i, automation.conditions[i])"
|
@resetFilter="resetFilter(i, automation.conditions[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
:show-action-input="
|
:show-action-input="
|
||||||
showActionInput(automation.actions[i].action_name)
|
showActionInput(automation.actions[i].action_name)
|
||||||
"
|
"
|
||||||
:v="$v.automation.actions.$each[i]"
|
:v="v$.automation.actions.$each[i]"
|
||||||
@resetAction="resetAction(i)"
|
@resetAction="resetAction(i)"
|
||||||
@removeAction="removeAction(i)"
|
@removeAction="removeAction(i)"
|
||||||
/>
|
/>
|
||||||
@@ -228,6 +228,7 @@ export default {
|
|||||||
select {
|
select {
|
||||||
@apply m-0;
|
@apply m-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-message {
|
.info-message {
|
||||||
@apply text-xs text-green-500 dark:text-green-500 text-right;
|
@apply text-xs text-green-500 dark:text-green-500 text-right;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -7,30 +7,30 @@
|
|||||||
v-model="automation.name"
|
v-model="automation.name"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.name.$error }"
|
:class="{ error: v$.automation.name.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.name.$error
|
v$.automation.name.$error
|
||||||
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.automation.name.$touch"
|
@blur="v$.automation.name.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="automation.description"
|
v-model="automation.description"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.description.$error }"
|
:class="{ error: v$.automation.description.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.description.$error
|
v$.automation.description.$error
|
||||||
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.automation.description.$touch"
|
@blur="v$.automation.description.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="event_wrapper">
|
<div class="event_wrapper">
|
||||||
<label :class="{ error: $v.automation.event_name.$error }">
|
<label :class="{ error: v$.automation.event_name.$error }">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
||||||
<select v-model="automation.event_name" @change="onEventChange()">
|
<select v-model="automation.event_name" @change="onEventChange()">
|
||||||
<option
|
<option
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
{{ event.value }}
|
{{ event.value }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.automation.event_name.$error" class="message">
|
<span v-if="v$.automation.event_name.$error" class="message">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
getCustomAttributeType(automation.conditions[i].attribute_key)
|
getCustomAttributeType(automation.conditions[i].attribute_key)
|
||||||
"
|
"
|
||||||
:show-query-operator="i !== automation.conditions.length - 1"
|
:show-query-operator="i !== automation.conditions.length - 1"
|
||||||
:v="$v.automation.conditions.$each[i]"
|
:v="v$.automation.conditions.$each[i]"
|
||||||
@resetFilter="resetFilter(i, automation.conditions[i])"
|
@resetFilter="resetFilter(i, automation.conditions[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
:action-types="automationActionTypes"
|
:action-types="automationActionTypes"
|
||||||
:dropdown-values="getActionDropdownValues(action.action_name)"
|
:dropdown-values="getActionDropdownValues(action.action_name)"
|
||||||
:show-action-input="showActionInput(action.action_name)"
|
:show-action-input="showActionInput(action.action_name)"
|
||||||
:v="$v.automation.actions.$each[i]"
|
:v="v$.automation.actions.$each[i]"
|
||||||
:initial-file-name="getFileName(action, automation.files)"
|
:initial-file-name="getFileName(action, automation.files)"
|
||||||
@resetAction="resetAction(i)"
|
@resetAction="resetAction(i)"
|
||||||
@removeAction="removeAction(i)"
|
@removeAction="removeAction(i)"
|
||||||
@@ -206,6 +206,7 @@ export default {
|
|||||||
select {
|
select {
|
||||||
@apply m-0;
|
@apply m-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-message {
|
.info-message {
|
||||||
@apply text-xs text-green-500 dark:text-green-500 text-right;
|
@apply text-xs text-green-500 dark:text-green-500 text-right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
v-model="title"
|
v-model="title"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
:error="$v.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
:error="v$.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
||||||
@blur="$v.title.$touch"
|
@blur="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="isOngoingType" class="editor-wrap">
|
<div v-if="isOngoingType" class="editor-wrap">
|
||||||
@@ -24,38 +24,38 @@
|
|||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label v-else :class="{ error: $v.message.$error }">
|
<label v-else :class="{ error: v$.message.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="message"
|
v-model="message"
|
||||||
rows="5"
|
rows="5"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="message">
|
<span v-if="v$.message.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedInbox.$error }">
|
<label :class="{ error: v$.selectedInbox.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
||||||
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
||||||
<option v-for="item in inboxes" :key="item.name" :value="item.id">
|
<option v-for="item in inboxes" :key="item.name" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedInbox.$error" class="message">
|
<span v-if="v$.selectedInbox.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
<label
|
<label
|
||||||
v-if="isOnOffType"
|
v-if="isOnOffType"
|
||||||
class="multiselect-wrap--small"
|
class="multiselect-wrap--small"
|
||||||
:class="{ error: $v.selectedAudience.$error }"
|
:class="{ error: v$.selectedAudience.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
|
||||||
<multiselect
|
<multiselect
|
||||||
@@ -79,17 +79,17 @@
|
|||||||
selected-label
|
selected-label
|
||||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||||
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
||||||
@blur="$v.selectedAudience.$touch"
|
@blur="v$.selectedAudience.$touch"
|
||||||
@select="$v.selectedAudience.$touch"
|
@select="v$.selectedAudience.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.selectedAudience.$error" class="message">
|
<span v-if="v$.selectedAudience.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
v-if="isOngoingType"
|
v-if="isOngoingType"
|
||||||
:class="{ error: $v.selectedSender.$error }"
|
:class="{ error: v$.selectedSender.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
||||||
<select v-model="selectedSender">
|
<select v-model="selectedSender">
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
{{ sender.name }}
|
{{ sender.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedSender.$error" class="message">
|
<span v-if="v$.selectedSender.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -121,26 +121,26 @@
|
|||||||
v-model="endPoint"
|
v-model="endPoint"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.endPoint.$error }"
|
:class="{ error: v$.endPoint.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
v$.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
||||||
@blur="$v.endPoint.$touch"
|
@blur="v$.endPoint.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isOngoingType"
|
v-if="isOngoingType"
|
||||||
v-model="timeOnPage"
|
v-model="timeOnPage"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.timeOnPage.$error }"
|
:class="{ error: v$.timeOnPage.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.timeOnPage.$error
|
v$.timeOnPage.$error
|
||||||
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
||||||
@blur="$v.timeOnPage.$touch"
|
@blur="v$.timeOnPage.$touch"
|
||||||
/>
|
/>
|
||||||
<label v-if="isOngoingType">
|
<label v-if="isOngoingType">
|
||||||
<input
|
<input
|
||||||
@@ -176,13 +176,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import campaignMixin from 'shared/mixins/campaignMixin';
|
||||||
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
|
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
|
||||||
import { URLPattern } from 'urlpattern-polyfill';
|
import { URLPattern } from 'urlpattern-polyfill';
|
||||||
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -191,6 +192,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mixins: [alertMixin, campaignMixin],
|
mixins: [alertMixin, campaignMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -343,8 +347,8 @@ export default {
|
|||||||
return campaignDetails;
|
return campaignDetails;
|
||||||
},
|
},
|
||||||
async addCampaign() {
|
async addCampaign() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
v-model="title"
|
v-model="title"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
:error="$v.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
:error="v$.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
||||||
@blur="$v.title.$touch"
|
@blur="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<label>
|
<label>
|
||||||
@@ -20,28 +20,28 @@
|
|||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:is-format-mode="true"
|
:is-format-mode="true"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@input="$v.message.$touch"
|
@input="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedInbox.$error }">
|
<label :class="{ error: v$.selectedInbox.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
||||||
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
||||||
<option v-for="item in inboxes" :key="item.id" :value="item.id">
|
<option v-for="item in inboxes" :key="item.id" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedInbox.$error" class="message">
|
<span v-if="v$.selectedInbox.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedSender.$error }">
|
<label :class="{ error: v$.selectedSender.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
||||||
<select v-model="selectedSender">
|
<select v-model="selectedSender">
|
||||||
<option
|
<option
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
{{ sender.name }}
|
{{ sender.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedSender.$error" class="message">
|
<span v-if="v$.selectedSender.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -60,25 +60,25 @@
|
|||||||
v-model="endPoint"
|
v-model="endPoint"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.endPoint.$error }"
|
:class="{ error: v$.endPoint.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
v$.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
||||||
@blur="$v.endPoint.$touch"
|
@blur="v$.endPoint.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="timeOnPage"
|
v-model="timeOnPage"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.timeOnPage.$error }"
|
:class="{ error: v$.timeOnPage.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.timeOnPage.$error
|
v$.timeOnPage.$error
|
||||||
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
||||||
@blur="$v.timeOnPage.$touch"
|
@blur="v$.timeOnPage.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -113,11 +113,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import campaignMixin from 'shared/mixins/campaignMixin';
|
||||||
import { URLPattern } from 'urlpattern-polyfill';
|
import { URLPattern } from 'urlpattern-polyfill';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -130,6 +131,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -252,8 +256,8 @@ export default {
|
|||||||
this.loadInboxMembers();
|
this.loadInboxMembers();
|
||||||
},
|
},
|
||||||
async editCampaign() {
|
async editCampaign() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,38 +7,38 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-col w-full" @submit.prevent="addCannedResponse()">
|
<form class="flex flex-col w-full" @submit.prevent="addCannedResponse()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.shortCode.$error }">
|
<label :class="{ error: v$.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="shortCode"
|
v-model.trim="shortCode"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
@input="$v.shortCode.$touch"
|
@input="v$.shortCode.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.content.$error }">
|
<label :class="{ error: v$.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="content"
|
v-model="content"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.content.$error }"
|
:class="{ editor_warning: v$.content.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:enable-canned-responses="false"
|
:enable-canned-responses="false"
|
||||||
:placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')"
|
||||||
@blur="$v.content.$touch"
|
@blur="v$.content.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.content.$invalid ||
|
v$.content.$invalid ||
|
||||||
$v.shortCode.$invalid ||
|
v$.shortCode.$invalid ||
|
||||||
addCanned.showLoading
|
addCanned.showLoading
|
||||||
"
|
"
|
||||||
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
||||||
@@ -54,12 +54,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
import Modal from '../../../../components/Modal.vue';
|
import Modal from '../../../../components/Modal.vue';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -78,6 +79,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shortCode: '',
|
shortCode: '',
|
||||||
@@ -102,8 +106,8 @@ export default {
|
|||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = '';
|
this.shortCode = '';
|
||||||
this.content = '';
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.v$.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.v$.content.$reset();
|
||||||
},
|
},
|
||||||
addCannedResponse() {
|
addCannedResponse() {
|
||||||
// Show loading on button
|
// Show loading on button
|
||||||
|
|||||||
@@ -4,38 +4,38 @@
|
|||||||
<woot-modal-header :header-title="pageTitle" />
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
<form class="flex flex-col w-full" @submit.prevent="editCannedResponse()">
|
<form class="flex flex-col w-full" @submit.prevent="editCannedResponse()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.shortCode.$error }">
|
<label :class="{ error: v$.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="shortCode"
|
v-model.trim="shortCode"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
@input="$v.shortCode.$touch"
|
@input="v$.shortCode.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.content.$error }">
|
<label :class="{ error: v$.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="content"
|
v-model="content"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.content.$error }"
|
:class="{ editor_warning: v$.content.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:enable-canned-responses="false"
|
:enable-canned-responses="false"
|
||||||
:placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')"
|
||||||
@blur="$v.content.$touch"
|
@blur="v$.content.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.content.$invalid ||
|
v$.content.$invalid ||
|
||||||
$v.shortCode.$invalid ||
|
v$.shortCode.$invalid ||
|
||||||
editCanned.showLoading
|
editCanned.showLoading
|
||||||
"
|
"
|
||||||
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
||||||
@@ -52,11 +52,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import Modal from '../../../../components/Modal.vue';
|
import Modal from '../../../../components/Modal.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -71,6 +72,9 @@ export default {
|
|||||||
edshortCode: { type: String, default: '' },
|
edshortCode: { type: String, default: '' },
|
||||||
onClose: { type: Function, default: () => {} },
|
onClose: { type: Function, default: () => {} },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editCanned: {
|
editCanned: {
|
||||||
@@ -98,14 +102,14 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setPageName({ name }) {
|
setPageName({ name }) {
|
||||||
this.$v.content.$touch();
|
this.v$.content.$touch();
|
||||||
this.content = name;
|
this.content = name;
|
||||||
},
|
},
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = '';
|
this.shortCode = '';
|
||||||
this.content = '';
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.v$.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.v$.content.$reset();
|
||||||
},
|
},
|
||||||
editCannedResponse() {
|
editCannedResponse() {
|
||||||
// Show loading on button
|
// Show loading on button
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-[60%]">
|
<div class="w-[60%]">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.selectedAgents.$error }">
|
<label :class="{ error: v$.selectedAgents.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.AGENTS.TITLE') }}
|
{{ $t('INBOX_MGMT.ADD.AGENTS.TITLE') }}
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model="selectedAgents"
|
v-model="selectedAgents"
|
||||||
@@ -24,9 +24,9 @@
|
|||||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||||
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.AGENTS.PICK_AGENTS')"
|
:placeholder="$t('INBOX_MGMT.ADD.AGENTS.PICK_AGENTS')"
|
||||||
@select="$v.selectedAgents.$touch"
|
@select="v$.selectedAgents.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.selectedAgents.$error" class="message">
|
<span v-if="v$.selectedAgents.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.AGENTS.VALIDATION_ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.AGENTS.VALIDATION_ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -18,37 +18,37 @@
|
|||||||
<div v-if="isIMAPEnabled" class="imap-details-wrap">
|
<div v-if="isIMAPEnabled" class="imap-details-wrap">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="address"
|
v-model.trim="address"
|
||||||
:class="{ error: $v.address.$error }"
|
:class="{ error: v$.address.$error }"
|
||||||
class="medium-9 columns"
|
class="medium-9 columns"
|
||||||
:label="$t('INBOX_MGMT.IMAP.ADDRESS.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.ADDRESS.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.ADDRESS.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.ADDRESS.PLACE_HOLDER')"
|
||||||
@blur="$v.address.$touch"
|
@blur="v$.address.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="port"
|
v-model="port"
|
||||||
type="number"
|
type="number"
|
||||||
:class="{ error: $v.port.$error }"
|
:class="{ error: v$.port.$error }"
|
||||||
class="medium-9 columns"
|
class="medium-9 columns"
|
||||||
:label="$t('INBOX_MGMT.IMAP.PORT.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.PORT.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.PORT.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.PORT.PLACE_HOLDER')"
|
||||||
@blur="$v.port.$touch"
|
@blur="v$.port.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="login"
|
v-model="login"
|
||||||
:class="{ error: $v.login.$error }"
|
:class="{ error: v$.login.$error }"
|
||||||
class="medium-9 columns"
|
class="medium-9 columns"
|
||||||
:label="$t('INBOX_MGMT.IMAP.LOGIN.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.LOGIN.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.LOGIN.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.LOGIN.PLACE_HOLDER')"
|
||||||
@blur="$v.login.$touch"
|
@blur="v$.login.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="password"
|
v-model="password"
|
||||||
:class="{ error: $v.password.$error }"
|
:class="{ error: v$.password.$error }"
|
||||||
class="medium-9 columns"
|
class="medium-9 columns"
|
||||||
:label="$t('INBOX_MGMT.IMAP.PASSWORD.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.PASSWORD.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.PASSWORD.PLACE_HOLDER')"
|
||||||
type="password"
|
type="password"
|
||||||
@blur="$v.password.$touch"
|
@blur="v$.password.$touch"
|
||||||
/>
|
/>
|
||||||
<label for="toggle-enable-ssl">
|
<label for="toggle-enable-ssl">
|
||||||
<input
|
<input
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:button-text="$t('INBOX_MGMT.IMAP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.IMAP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdatingIMAP"
|
:loading="uiFlags.isUpdatingIMAP"
|
||||||
:disabled="($v.$invalid && isIMAPEnabled) || uiFlags.isUpdatingIMAP"
|
:disabled="(v$.$invalid && isIMAPEnabled) || uiFlags.isUpdatingIMAP"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</settings-section>
|
</settings-section>
|
||||||
@@ -73,7 +73,8 @@
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -86,6 +87,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isIMAPEnabled: false,
|
isIMAPEnabled: false,
|
||||||
|
|||||||
@@ -38,21 +38,21 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="selectedInboxName"
|
v-model.trim="selectedInboxName"
|
||||||
class="w-[75%] pb-4"
|
class="w-[75%] pb-4"
|
||||||
:class="{ error: $v.selectedInboxName.$error }"
|
:class="{ error: v$.selectedInboxName.$error }"
|
||||||
:label="inboxNameLabel"
|
:label="inboxNameLabel"
|
||||||
:placeholder="inboxNamePlaceHolder"
|
:placeholder="inboxNamePlaceHolder"
|
||||||
:error="
|
:error="
|
||||||
$v.selectedInboxName.$error
|
v$.selectedInboxName.$error
|
||||||
? $t('INBOX_MGMT.ADD.CHANNEL_NAME.ERROR')
|
? $t('INBOX_MGMT.ADD.CHANNEL_NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
@blur="$v.selectedInboxName.$touch"
|
@blur="v$.selectedInboxName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isAPIInbox"
|
v-if="isAPIInbox"
|
||||||
v-model.trim="webhookUrl"
|
v-model.trim="webhookUrl"
|
||||||
class="w-[75%] pb-4"
|
class="w-[75%] pb-4"
|
||||||
:class="{ error: $v.webhookUrl.$error }"
|
:class="{ error: v$.webhookUrl.$error }"
|
||||||
:label="
|
:label="
|
||||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.LABEL')
|
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.LABEL')
|
||||||
"
|
"
|
||||||
@@ -60,11 +60,11 @@
|
|||||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
:error="
|
:error="
|
||||||
$v.webhookUrl.$error
|
v$.webhookUrl.$error
|
||||||
? $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.ERROR')
|
? $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
@blur="$v.webhookUrl.$touch"
|
@blur="v$.webhookUrl.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isAWebWidgetInbox"
|
v-if="isAWebWidgetInbox"
|
||||||
@@ -383,7 +383,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
v-if="isAPIInbox"
|
v-if="isAPIInbox"
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="$v.webhookUrl.$invalid"
|
:disabled="v$.webhookUrl.$invalid"
|
||||||
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdating"
|
:loading="uiFlags.isUpdating"
|
||||||
@click="updateInbox"
|
@click="updateInbox"
|
||||||
@@ -391,7 +391,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
v-else
|
v-else
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="$v.$invalid"
|
:disabled="v$.$invalid"
|
||||||
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdating"
|
:loading="uiFlags.isUpdating"
|
||||||
@click="updateInbox"
|
@click="updateInbox"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user