Compare commits

...
Author SHA1 Message Date
Pranav Raj S 46b91ad840 Running version 2024-01-27 23:33:15 -08:00
Pranav Raj S ed8b58ad10 Remove foundation 2024-01-27 23:25:10 -08:00
Pranav Raj S 4928f28c64 Remove ionicons 2024-01-27 23:23:27 -08:00
Pranav Raj S 30539c27f2 Merge branch 'develop' into vite-ruby-migration 2024-01-27 23:21:44 -08:00
Pranav Raj S 2e747e7fa6 Remove webpack 2024-01-25 12:43:39 -08:00
Pranav Raj S a1b6b0c06c Running dashboard, help center 2024-01-25 12:32:50 -08:00
Pranav Raj S 1fe3960285 Upgrade @vuelidate to 2.x 2024-01-25 12:15:21 -08:00
Pranav Raj S c33c844039 Initial Vite Commit 2024-01-25 11:56:22 -08:00
191 changed files with 1926 additions and 14682 deletions
+1 -1
View File
@@ -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:
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+9 -1
View File
@@ -75,4 +75,12 @@ yalc.lock
yarn-debug.log* 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
+1 -3
View File
@@ -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;
}, },
})); }));
+1 -1
View File
@@ -64,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'
+10 -8
View File
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -957,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
View File
@@ -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
View File
@@ -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
@@ -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;
@@ -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 {
@@ -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,12 +122,13 @@
<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'; 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: {
@@ -149,6 +150,9 @@ export default {
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,
@@ -206,13 +210,13 @@ 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) { if (!this.v$.editedValue.regexValidation) {
return this.regexCue return this.regexCue
? this.regexCue ? this.regexCue
: this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_INPUT'); : this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_INPUT');
@@ -280,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;
@@ -302,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;
} }
@@ -323,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;
} }
@@ -332,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;
} }
+15 -15
View File
@@ -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,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;
@@ -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;
} }
@@ -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;
} }
@@ -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;
@@ -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: '',
@@ -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: {
@@ -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;
@@ -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 {
@@ -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: [
@@ -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;
} }
@@ -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';
@@ -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;
} }
@@ -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 = [
{ {
@@ -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 {
@@ -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);
} }
@@ -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 },
@@ -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;
@@ -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;
} }
@@ -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>
@@ -126,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],
@@ -140,6 +141,9 @@ export default {
default: () => {}, default: () => {},
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
@@ -175,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');
@@ -238,8 +242,8 @@ export default {
this.regexEnabled = !this.regexEnabled; 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) { if (!this.regexEnabled) {
@@ -277,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 {
@@ -292,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>
@@ -109,12 +109,13 @@
<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 customAttributeMixin from '../../../../mixins/customAttributeMixin';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: {},
mixins: [alertMixin, customAttributeMixin], mixins: [alertMixin, customAttributeMixin],
props: { props: {
selectedAttribute: { selectedAttribute: {
@@ -126,6 +127,9 @@ export default {
default: false, default: false,
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
displayName: '', displayName: '',
@@ -173,7 +177,7 @@ 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 (
@@ -194,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');
@@ -237,8 +241,8 @@ export default {
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) { if (!this.regexEnabled) {
@@ -277,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 {
@@ -292,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,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;
} }
@@ -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"
@@ -17,45 +17,45 @@
<div v-if="isSMTPEnabled" class="smtp-details-wrap"> <div v-if="isSMTPEnabled" class="smtp-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.SMTP.ADDRESS.LABEL')" :label="$t('INBOX_MGMT.SMTP.ADDRESS.LABEL')"
:placeholder="$t('INBOX_MGMT.SMTP.ADDRESS.PLACE_HOLDER')" :placeholder="$t('INBOX_MGMT.SMTP.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.SMTP.PORT.LABEL')" :label="$t('INBOX_MGMT.SMTP.PORT.LABEL')"
:placeholder="$t('INBOX_MGMT.SMTP.PORT.PLACE_HOLDER')" :placeholder="$t('INBOX_MGMT.SMTP.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.SMTP.LOGIN.LABEL')" :label="$t('INBOX_MGMT.SMTP.LOGIN.LABEL')"
:placeholder="$t('INBOX_MGMT.SMTP.LOGIN.PLACE_HOLDER')" :placeholder="$t('INBOX_MGMT.SMTP.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.SMTP.PASSWORD.LABEL')" :label="$t('INBOX_MGMT.SMTP.PASSWORD.LABEL')"
:placeholder="$t('INBOX_MGMT.SMTP.PASSWORD.PLACE_HOLDER')" :placeholder="$t('INBOX_MGMT.SMTP.PASSWORD.PLACE_HOLDER')"
type="password" type="password"
@blur="$v.password.$touch" @blur="v$.password.$touch"
/> />
<woot-input <woot-input
v-model.trim="domain" v-model.trim="domain"
:class="{ error: $v.domain.$error }" :class="{ error: v$.domain.$error }"
class="medium-9 columns" class="medium-9 columns"
:label="$t('INBOX_MGMT.SMTP.DOMAIN.LABEL')" :label="$t('INBOX_MGMT.SMTP.DOMAIN.LABEL')"
:placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')" :placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')"
@blur="$v.domain.$touch" @blur="v$.domain.$touch"
/> />
<input-radio-group <input-radio-group
:label="$t('INBOX_MGMT.SMTP.ENCRYPTION')" :label="$t('INBOX_MGMT.SMTP.ENCRYPTION')"
@@ -80,7 +80,7 @@
<woot-submit-button <woot-submit-button
:button-text="$t('INBOX_MGMT.SMTP.UPDATE')" :button-text="$t('INBOX_MGMT.SMTP.UPDATE')"
:loading="uiFlags.isUpdatingSMTP" :loading="uiFlags.isUpdatingSMTP"
:disabled="($v.$invalid && isSMTPEnabled) || uiFlags.isUpdatingSMTP" :disabled="(v$.$invalid && isSMTPEnabled) || uiFlags.isUpdatingSMTP"
/> />
</form> </form>
</settings-section> </settings-section>
@@ -91,9 +91,10 @@
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 InputRadioGroup from './components/InputRadioGroup.vue'; import InputRadioGroup from './components/InputRadioGroup.vue';
import SingleSelectDropdown from './components/SingleSelectDropdown.vue'; import SingleSelectDropdown from './components/SingleSelectDropdown.vue';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -108,6 +109,9 @@ export default {
default: () => ({}), default: () => ({}),
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
isSMTPEnabled: false, isSMTPEnabled: false,
@@ -5,9 +5,8 @@
<div class="settings-content"> <div class="settings-content">
<form @submit.prevent="updateWidget"> <form @submit.prevent="updateWidget">
<woot-avatar-uploader <woot-avatar-uploader
:label=" :label="$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.AVATAR.LABEL')
$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.AVATAR.LABEL') "
"
:src="avatarUrl" :src="avatarUrl"
delete-avatar delete-avatar
@change="handleImageUpload" @change="handleImageUpload"
@@ -15,45 +14,39 @@
/> />
<woot-input <woot-input
v-model.trim="websiteName" v-model.trim="websiteName"
:class="{ error: $v.websiteName.$error }" :class="{ error: v$.websiteName.$error }"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.LABEL' )
) "
" :placeholder="$t(
:placeholder=" 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.PLACE_HOLDER'
$t( )
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.PLACE_HOLDER' "
)
"
:error="websiteNameValidationErrorMsg" :error="websiteNameValidationErrorMsg"
@blur="$v.websiteName.$touch" @blur="v$.websiteName.$touch"
/> />
<woot-input <woot-input
v-model.trim="welcomeHeading" v-model.trim="welcomeHeading"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_HEADING.LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_HEADING.LABEL' )
) "
" :placeholder="$t(
:placeholder=" 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_HEADING.PLACE_HOLDER'
$t( )
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_HEADING.PLACE_HOLDER' "
)
"
/> />
<woot-input <woot-input
v-model.trim="welcomeTagline" v-model.trim="welcomeTagline"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_TAGLINE.LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_TAGLINE.LABEL' )
) "
" :placeholder="$t(
:placeholder=" 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_TAGLINE.PLACE_HOLDER'
$t( )
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WELCOME_TAGLINE.PLACE_HOLDER' "
)
"
/> />
<label> <label>
{{ {{
@@ -79,46 +72,41 @@
</label> </label>
<input-radio-group <input-radio-group
name="widget-bubble-position" name="widget-bubble-position"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_POSITION_LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_POSITION_LABEL' )
) "
"
:items="widgetBubblePositions" :items="widgetBubblePositions"
:action="handleWidgetBubblePositionChange" :action="handleWidgetBubblePositionChange"
/> />
<input-radio-group <input-radio-group
name="widget-bubble-type" name="widget-bubble-type"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_TYPE_LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_TYPE_LABEL' )
) "
"
:items="widgetBubbleTypes" :items="widgetBubbleTypes"
:action="handleWidgetBubbleTypeChange" :action="handleWidgetBubbleTypeChange"
/> />
<woot-input <woot-input
v-model.trim="widgetBubbleLauncherTitle" v-model.trim="widgetBubbleLauncherTitle"
:label=" :label="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_LAUNCHER_TITLE.LABEL'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_LAUNCHER_TITLE.LABEL' )
) "
" :placeholder="$t(
:placeholder=" 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_LAUNCHER_TITLE.PLACE_HOLDER'
$t( )
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WIDGET_BUBBLE_LAUNCHER_TITLE.PLACE_HOLDER' "
)
"
/> />
<woot-submit-button <woot-submit-button
class="submit-button" class="submit-button"
:button-text=" :button-text="$t(
$t( 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.UPDATE.BUTTON_TEXT'
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.UPDATE.BUTTON_TEXT' )
) "
"
:loading="uiFlags.isUpdating" :loading="uiFlags.isUpdating"
:disabled="$v.$invalid || uiFlags.isUpdating" :disabled="v$.$invalid || uiFlags.isUpdating"
/> />
</form> </form>
</div> </div>
@@ -130,7 +118,10 @@
:action="handleWidgetViewChange" :action="handleWidgetViewChange"
:style="{ 'text-align': 'center' }" :style="{ 'text-align': 'center' }"
/> />
<div v-if="isWidgetPreview" class="widget-preview"> <div
v-if="isWidgetPreview"
class="widget-preview"
>
<Widget <Widget
:welcome-heading="welcomeHeading" :welcome-heading="welcomeHeading"
:welcome-tagline="welcomeTagline" :welcome-tagline="welcomeTagline"
@@ -144,7 +135,10 @@
:widget-bubble-type="widgetBubbleType" :widget-bubble-type="widgetBubbleType"
/> />
</div> </div>
<div v-else class="widget-script"> <div
v-else
class="widget-script"
>
<woot-code :script="widgetScript" /> <woot-code :script="widgetScript" />
</div> </div>
</div> </div>
@@ -157,9 +151,10 @@ import { mapGetters } from 'vuex';
import Widget from 'dashboard/modules/widget-preview/components/Widget.vue'; import Widget from 'dashboard/modules/widget-preview/components/Widget.vue';
import InputRadioGroup from './components/InputRadioGroup.vue'; import InputRadioGroup from './components/InputRadioGroup.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 { 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';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -170,9 +165,12 @@ export default {
props: { props: {
inbox: { inbox: {
type: Object, type: Object,
default: () => {}, default: () => { },
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
isWidgetPreview: true, isWidgetPreview: true,
@@ -288,7 +286,7 @@ export default {
]; ];
}, },
websiteNameValidationErrorMsg() { websiteNameValidationErrorMsg() {
return this.$v.websiteName.$error return this.v$.websiteName.$error
? this.$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.ERROR') ? this.$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.ERROR')
: ''; : '';
}, },
@@ -365,8 +363,8 @@ export default {
error.message error.message
? error.message ? error.message
: this.$t( : this.$t(
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.AVATAR.DELETE.API.ERROR_MESSAGE' 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.AVATAR.DELETE.API.ERROR_MESSAGE'
) )
); );
} }
}, },
@@ -402,9 +400,9 @@ export default {
} catch (error) { } catch (error) {
this.showAlert( this.showAlert(
error.message || error.message ||
this.$t( this.$t(
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.UPDATE.API.ERROR_MESSAGE' 'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.UPDATE.API.ERROR_MESSAGE'
) )
); );
} }
}, },
@@ -416,15 +414,12 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~dashboard/assets/scss/woot'; @import 'dashboard/assets/scss/woot';
.widget-builder-container { .widget-builder-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
padding: var(--space-one); padding: var(--space-one);
@include breakpoint(900px down) {
flex-direction: column;
}
} }
.settings-container { .settings-container {
@@ -450,10 +445,11 @@ export default {
padding: var(--space-one) var(--space-one) var(--space-one) var(--space-one); padding: var(--space-one) var(--space-one) var(--space-one) var(--space-one);
@apply bg-slate-50 dark:bg-slate-700; @apply bg-slate-50 dark:bg-slate-700;
@include breakpoint(500px down) { // @include breakpoint(500px down) {
background: none; // background: none;
} // }
} }
.widget-script { .widget-script {
@apply mx-5 p-2.5 bg-slate-50 dark:bg-slate-700; @apply mx-5 p-2.5 bg-slate-50 dark:bg-slate-700;
} }
@@ -1,12 +1,12 @@
import Facebook from './channels/Facebook'; import Facebook from './channels/Facebook.vue';
import Website from './channels/Website'; import Website from './channels/Website.vue';
import Twitter from './channels/Twitter'; import Twitter from './channels/Twitter.vue';
import Api from './channels/Api'; import Api from './channels/Api.vue';
import Email from './channels/Email'; import Email from './channels/Email.vue';
import Sms from './channels/Sms'; import Sms from './channels/Sms.vue';
import Whatsapp from './channels/Whatsapp'; import Whatsapp from './channels/Whatsapp.vue';
import Line from './channels/Line'; import Line from './channels/Line.vue';
import Telegram from './channels/Telegram'; import Telegram from './channels/Telegram.vue';
const channelViewList = { const channelViewList = {
facebook: Facebook, facebook: Facebook,
@@ -1,37 +1,37 @@
<template> <template>
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.inboxName.$error }"> <label :class="{ error: v$.inboxName.$error }">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
<input <input
v-model.trim="inboxName" v-model.trim="inboxName"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
@blur="$v.inboxName.$touch" @blur="v$.inboxName.$touch"
/> />
<span v-if="$v.inboxName.$error" class="message"> <span v-if="v$.inboxName.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.phoneNumber.$error }"> <label :class="{ error: v$.phoneNumber.$error }">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
<input <input
v-model.trim="phoneNumber" v-model.trim="phoneNumber"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
@blur="$v.phoneNumber.$touch" @blur="v$.phoneNumber.$touch"
/> />
<span v-if="$v.phoneNumber.$error" class="message"> <span v-if="v$.phoneNumber.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.apiKey.$error }"> <label :class="{ error: v$.apiKey.$error }">
<span> <span>
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
</span> </span>
@@ -39,9 +39,9 @@
v-model.trim="apiKey" v-model.trim="apiKey"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
@blur="$v.apiKey.$touch" @blur="v$.apiKey.$touch"
/> />
<span v-if="$v.apiKey.$error" class="message"> <span v-if="v$.apiKey.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
</span> </span>
</label> </label>
@@ -59,13 +59,17 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators'; import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
inboxName: '', inboxName: '',
@@ -83,8 +87,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -6,7 +6,7 @@
/> />
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.channelName.$error }"> <label :class="{ error: v$.channelName.$error }">
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.LABEL') }}
<input <input
v-model.trim="channelName" v-model.trim="channelName"
@@ -14,16 +14,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.PLACEHOLDER') $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
" "
@blur="$v.channelName.$touch" @blur="v$.channelName.$touch"
/> />
<span v-if="$v.channelName.$error" class="message">{{ <span v-if="v$.channelName.$error" class="message">{{
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.ERROR') $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.webhookUrl.$error }"> <label :class="{ error: v$.webhookUrl.$error }">
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.LABEL') }} {{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.LABEL') }}
<input <input
v-model.trim="webhookUrl" v-model.trim="webhookUrl"
@@ -31,7 +31,7 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.PLACEHOLDER') $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.PLACEHOLDER')
" "
@blur="$v.webhookUrl.$touch" @blur="v$.webhookUrl.$touch"
/> />
</label> </label>
<p class="help-text"> <p class="help-text">
@@ -52,9 +52,10 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import PageHeader from '../../SettingsSubPageHeader.vue'; import PageHeader from '../../SettingsSubPageHeader.vue';
import { useVuelidate } from '@vuelidate/core';
const shouldBeWebhookUrl = (value = '') => const shouldBeWebhookUrl = (value = '') =>
value ? value.startsWith('http') : true; value ? value.startsWith('http') : true;
@@ -64,6 +65,9 @@ export default {
PageHeader, PageHeader,
}, },
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
channelName: '', channelName: '',
@@ -81,8 +85,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -1,7 +1,7 @@
<template> <template>
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.inboxName.$error }"> <label :class="{ error: v$.inboxName.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.LABEL') }}
<input <input
v-model.trim="inboxName" v-model.trim="inboxName"
@@ -9,16 +9,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.PLACEHOLDER') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.PLACEHOLDER')
" "
@blur="$v.inboxName.$touch" @blur="v$.inboxName.$touch"
/> />
<span v-if="$v.inboxName.$error" class="message">{{ <span v-if="v$.inboxName.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.phoneNumber.$error }"> <label :class="{ error: v$.phoneNumber.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.LABEL') }}
<input <input
v-model.trim="phoneNumber" v-model.trim="phoneNumber"
@@ -26,16 +26,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.PLACEHOLDER') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.PLACEHOLDER')
" "
@blur="$v.phoneNumber.$touch" @blur="v$.phoneNumber.$touch"
/> />
<span v-if="$v.phoneNumber.$error" class="message">{{ <span v-if="v$.phoneNumber.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.accountId.$error }"> <label :class="{ error: v$.accountId.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.LABEL') }}
<input <input
v-model.trim="accountId" v-model.trim="accountId"
@@ -43,16 +43,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.PLACEHOLDER') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.PLACEHOLDER')
" "
@blur="$v.accountId.$touch" @blur="v$.accountId.$touch"
/> />
<span v-if="$v.accountId.$error" class="message">{{ <span v-if="v$.accountId.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.applicationId.$error }"> <label :class="{ error: v$.applicationId.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.LABEL') }}
<input <input
v-model.trim="applicationId" v-model.trim="applicationId"
@@ -60,31 +60,31 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.PLACEHOLDER') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.PLACEHOLDER')
" "
@blur="$v.applicationId.$touch" @blur="v$.applicationId.$touch"
/> />
<span v-if="$v.applicationId.$error" class="message">{{ <span v-if="v$.applicationId.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.apiKey.$error }"> <label :class="{ error: v$.apiKey.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.LABEL') }}
<input <input
v-model.trim="apiKey" v-model.trim="apiKey"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.PLACEHOLDER')"
@blur="$v.apiKey.$touch" @blur="v$.apiKey.$touch"
/> />
<span v-if="$v.apiKey.$error" class="message">{{ <span v-if="v$.apiKey.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.apiSecret.$error }"> <label :class="{ error: v$.apiSecret.$error }">
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.LABEL') }} {{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.LABEL') }}
<input <input
v-model.trim="apiSecret" v-model.trim="apiSecret"
@@ -92,9 +92,9 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.PLACEHOLDER') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.PLACEHOLDER')
" "
@blur="$v.apiSecret.$touch" @blur="v$.apiSecret.$touch"
/> />
<span v-if="$v.apiSecret.$error" class="message">{{ <span v-if="v$.apiSecret.$error" class="message">{{
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.ERROR') $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.ERROR')
}}</span> }}</span>
</label> </label>
@@ -112,13 +112,17 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
const shouldStartWithPlusSign = (value = '') => value.startsWith('+'); const shouldStartWithPlusSign = (value = '') => value.startsWith('+');
import { useVuelidate } from '@vuelidate/core';
export default { export default {
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
accountId: '', accountId: '',
@@ -145,8 +149,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -1,37 +1,37 @@
<template> <template>
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.inboxName.$error }"> <label :class="{ error: v$.inboxName.$error }">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
<input <input
v-model.trim="inboxName" v-model.trim="inboxName"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
@blur="$v.inboxName.$touch" @blur="v$.inboxName.$touch"
/> />
<span v-if="$v.inboxName.$error" class="message"> <span v-if="v$.inboxName.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.phoneNumber.$error }"> <label :class="{ error: v$.phoneNumber.$error }">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
<input <input
v-model.trim="phoneNumber" v-model.trim="phoneNumber"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
@blur="$v.phoneNumber.$touch" @blur="v$.phoneNumber.$touch"
/> />
<span v-if="$v.phoneNumber.$error" class="message"> <span v-if="v$.phoneNumber.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.phoneNumberId.$error }"> <label :class="{ error: v$.phoneNumberId.$error }">
<span> <span>
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.LABEL') }}
</span> </span>
@@ -41,16 +41,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.PLACEHOLDER') $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.PLACEHOLDER')
" "
@blur="$v.phoneNumberId.$touch" @blur="v$.phoneNumberId.$touch"
/> />
<span v-if="$v.phoneNumberId.$error" class="message"> <span v-if="v$.phoneNumberId.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.businessAccountId.$error }"> <label :class="{ error: v$.businessAccountId.$error }">
<span> <span>
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.LABEL') }}
</span> </span>
@@ -60,16 +60,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.PLACEHOLDER') $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.PLACEHOLDER')
" "
@blur="$v.businessAccountId.$touch" @blur="v$.businessAccountId.$touch"
/> />
<span v-if="$v.businessAccountId.$error" class="message"> <span v-if="v$.businessAccountId.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.ERROR') }}
</span> </span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.apiKey.$error }"> <label :class="{ error: v$.apiKey.$error }">
<span> <span>
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
</span> </span>
@@ -77,9 +77,9 @@
v-model.trim="apiKey" v-model.trim="apiKey"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
@blur="$v.apiKey.$touch" @blur="v$.apiKey.$touch"
/> />
<span v-if="$v.apiKey.$error" class="message"> <span v-if="v$.apiKey.$error" class="message">
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }} {{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
</span> </span>
</label> </label>
@@ -97,12 +97,16 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import { isPhoneE164OrEmpty, isNumber } from 'shared/helpers/Validators'; import { isPhoneE164OrEmpty, isNumber } from 'shared/helpers/Validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
inboxName: '', inboxName: '',
@@ -124,8 +128,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -43,7 +43,7 @@
</div> </div>
<div class="w-[60%]"> <div class="w-[60%]">
<div class="w-full"> <div class="w-full">
<div class="input-wrap" :class="{ error: $v.selectedPage.$error }"> <div class="input-wrap" :class="{ error: v$.selectedPage.$error }">
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PAGE') }} {{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PAGE') }}
<multiselect <multiselect
v-model.trim="selectedPage" v-model.trim="selectedPage"
@@ -58,21 +58,21 @@
selected-label selected-label
@select="setPageName" @select="setPageName"
/> />
<span v-if="$v.selectedPage.$error" class="message"> <span v-if="v$.selectedPage.$error" class="message">
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PLACEHOLDER') }} {{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PLACEHOLDER') }}
</span> </span>
</div> </div>
</div> </div>
<div class="w-full"> <div class="w-full">
<label :class="{ error: $v.pageName.$error }"> <label :class="{ error: v$.pageName.$error }">
{{ $t('INBOX_MGMT.ADD.FB.INBOX_NAME') }} {{ $t('INBOX_MGMT.ADD.FB.INBOX_NAME') }}
<input <input
v-model.trim="pageName" v-model.trim="pageName"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.FB.PICK_NAME')" :placeholder="$t('INBOX_MGMT.ADD.FB.PICK_NAME')"
@input="$v.pageName.$touch" @input="v$.pageName.$touch"
/> />
<span v-if="$v.pageName.$error" class="message"> <span v-if="v$.pageName.$error" class="message">
{{ $t('INBOX_MGMT.ADD.FB.ADD_NAME') }} {{ $t('INBOX_MGMT.ADD.FB.ADD_NAME') }}
</span> </span>
</label> </label>
@@ -88,7 +88,7 @@
<script> <script>
/* eslint-env browser */ /* eslint-env browser */
/* global FB */ /* global FB */
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import LoadingState from 'dashboard/components/widgets/LoadingState.vue'; import LoadingState from 'dashboard/components/widgets/LoadingState.vue';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import ChannelApi from '../../../../../api/channels'; import ChannelApi from '../../../../../api/channels';
@@ -96,6 +96,7 @@ import PageHeader from '../../SettingsSubPageHeader.vue';
import router from '../../../../index'; import router from '../../../../index';
import globalConfigMixin from 'shared/mixins/globalConfigMixin'; import globalConfigMixin from 'shared/mixins/globalConfigMixin';
import accountMixin from '../../../../../mixins/account'; import accountMixin from '../../../../../mixins/account';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -103,6 +104,9 @@ export default {
PageHeader, PageHeader,
}, },
mixins: [globalConfigMixin, accountMixin], mixins: [globalConfigMixin, accountMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
isCreating: false, isCreating: false,
@@ -161,7 +165,7 @@ export default {
}, },
setPageName({ name }) { setPageName({ name }) {
this.$v.selectedPage.$touch(); this.v$.selectedPage.$touch();
this.pageName = name; this.pageName = name;
}, },
@@ -263,8 +267,8 @@ export default {
}, },
createChannel() { createChannel() {
this.$v.$touch(); this.v$.$touch();
if (!this.$v.$error) { if (!this.v$.$error) {
this.emptyStateMessage = this.$t('INBOX_MGMT.DETAILS.CREATING_CHANNEL'); this.emptyStateMessage = this.$t('INBOX_MGMT.DETAILS.CREATING_CHANNEL');
this.isCreating = true; this.isCreating = true;
this.$store this.$store
@@ -6,7 +6,7 @@
/> />
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.channelName.$error }"> <label :class="{ error: v$.channelName.$error }">
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.LABEL') }}
<input <input
v-model.trim="channelName" v-model.trim="channelName"
@@ -14,16 +14,16 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.PLACEHOLDER') $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
" "
@blur="$v.channelName.$touch" @blur="v$.channelName.$touch"
/> />
<span v-if="$v.channelName.$error" class="message">{{ <span v-if="v$.channelName.$error" class="message">{{
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.ERROR') $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.lineChannelId.$error }"> <label :class="{ error: v$.lineChannelId.$error }">
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.LABEL') }} {{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.LABEL') }}
<input <input
v-model.trim="lineChannelId" v-model.trim="lineChannelId"
@@ -31,13 +31,13 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.PLACEHOLDER') $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.PLACEHOLDER')
" "
@blur="$v.lineChannelId.$touch" @blur="v$.lineChannelId.$touch"
/> />
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.lineChannelSecret.$error }"> <label :class="{ error: v$.lineChannelSecret.$error }">
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.LABEL') }} {{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.LABEL') }}
<input <input
v-model.trim="lineChannelSecret" v-model.trim="lineChannelSecret"
@@ -45,13 +45,13 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.PLACEHOLDER') $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.PLACEHOLDER')
" "
@blur="$v.lineChannelSecret.$touch" @blur="v$.lineChannelSecret.$touch"
/> />
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.lineChannelToken.$error }"> <label :class="{ error: v$.lineChannelToken.$error }">
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.LABEL') }} {{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.LABEL') }}
<input <input
v-model.trim="lineChannelToken" v-model.trim="lineChannelToken"
@@ -59,7 +59,7 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.PLACEHOLDER') $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.PLACEHOLDER')
" "
@blur="$v.lineChannelToken.$touch" @blur="v$.lineChannelToken.$touch"
/> />
</label> </label>
</div> </div>
@@ -77,15 +77,19 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import PageHeader from '../../SettingsSubPageHeader.vue'; import PageHeader from '../../SettingsSubPageHeader.vue';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
PageHeader, PageHeader,
}, },
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
channelName: '', channelName: '',
@@ -107,8 +111,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -6,7 +6,7 @@
/> />
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.botToken.$error }"> <label :class="{ error: v$.botToken.$error }">
{{ $t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.LABEL') }} {{ $t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.LABEL') }}
<input <input
v-model.trim="botToken" v-model.trim="botToken"
@@ -14,7 +14,7 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.PLACEHOLDER') $t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.PLACEHOLDER')
" "
@blur="$v.botToken.$touch" @blur="v$.botToken.$touch"
/> />
</label> </label>
<p class="help-text"> <p class="help-text">
@@ -35,15 +35,19 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import PageHeader from '../../SettingsSubPageHeader.vue'; import PageHeader from '../../SettingsSubPageHeader.vue';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
PageHeader, PageHeader,
}, },
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
botToken: '', botToken: '',
@@ -59,8 +63,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -2,15 +2,15 @@
<template> <template>
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.channelName.$error }"> <label :class="{ error: v$.channelName.$error }">
{{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.LABEL') }}
<input <input
v-model.trim="channelName" v-model.trim="channelName"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.PLACEHOLDER')"
@blur="$v.channelName.$touch" @blur="v$.channelName.$touch"
/> />
<span v-if="$v.channelName.$error" class="message">{{ <span v-if="v$.channelName.$error" class="message">{{
$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR') $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR')
}}</span> }}</span>
</label> </label>
@@ -19,7 +19,7 @@
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label <label
v-if="useMessagingService" v-if="useMessagingService"
:class="{ error: $v.messagingServiceSID.$error }" :class="{ error: v$.messagingServiceSID.$error }"
> >
{{ $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.LABEL') }} {{ $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.LABEL') }}
<input <input
@@ -28,9 +28,9 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.PLACEHOLDER') $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.PLACEHOLDER')
" "
@blur="$v.messagingServiceSID.$touch" @blur="v$.messagingServiceSID.$touch"
/> />
<span v-if="$v.messagingServiceSID.$error" class="message">{{ <span v-if="v$.messagingServiceSID.$error" class="message">{{
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.ERROR') $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.ERROR')
}}</span> }}</span>
</label> </label>
@@ -40,15 +40,15 @@
v-if="!useMessagingService" v-if="!useMessagingService"
class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]" class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"
> >
<label :class="{ error: $v.phoneNumber.$error }"> <label :class="{ error: v$.phoneNumber.$error }">
{{ $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.LABEL') }} {{ $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.LABEL') }}
<input <input
v-model.trim="phoneNumber" v-model.trim="phoneNumber"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.PLACEHOLDER')"
@blur="$v.phoneNumber.$touch" @blur="v$.phoneNumber.$touch"
/> />
<span v-if="$v.phoneNumber.$error" class="message">{{ <span v-if="v$.phoneNumber.$error" class="message">{{
$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR') $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR')
}}</span> }}</span>
</label> </label>
@@ -71,15 +71,15 @@
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.accountSID.$error }"> <label :class="{ error: v$.accountSID.$error }">
{{ $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.LABEL') }} {{ $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.LABEL') }}
<input <input
v-model.trim="accountSID" v-model.trim="accountSID"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.PLACEHOLDER')"
@blur="$v.accountSID.$touch" @blur="v$.accountSID.$touch"
/> />
<span v-if="$v.accountSID.$error" class="message">{{ <span v-if="v$.accountSID.$error" class="message">{{
$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR') $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR')
}}</span> }}</span>
</label> </label>
@@ -96,21 +96,21 @@
</label> </label>
</div> </div>
<div v-if="useAPIKey" class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div v-if="useAPIKey" class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.apiKeySID.$error }"> <label :class="{ error: v$.apiKeySID.$error }">
{{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.LABEL') }} {{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.LABEL') }}
<input <input
v-model.trim="apiKeySID" v-model.trim="apiKeySID"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.API_KEY.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.TWILIO.API_KEY.PLACEHOLDER')"
@blur="$v.apiKeySID.$touch" @blur="v$.apiKeySID.$touch"
/> />
<span v-if="$v.apiKeySID.$error" class="message">{{ <span v-if="v$.apiKeySID.$error" class="message">{{
$t('INBOX_MGMT.ADD.TWILIO.API_KEY.ERROR') $t('INBOX_MGMT.ADD.TWILIO.API_KEY.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.authToken.$error }"> <label :class="{ error: v$.authToken.$error }">
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.LABEL`) }} {{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.LABEL`) }}
<input <input
v-model.trim="authToken" v-model.trim="authToken"
@@ -118,9 +118,9 @@
:placeholder=" :placeholder="
$t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.PLACEHOLDER`) $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.PLACEHOLDER`)
" "
@blur="$v.authToken.$touch" @blur="v$.authToken.$touch"
/> />
<span v-if="$v.authToken.$error" class="message"> <span v-if="v$.authToken.$error" class="message">
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.ERROR`) }} {{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.ERROR`) }}
</span> </span>
</label> </label>
@@ -138,9 +138,10 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import router from '../../../../index'; import router from '../../../../index';
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators'; import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
mixins: [alertMixin], mixins: [alertMixin],
@@ -150,6 +151,9 @@ export default {
required: true, required: true,
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
accountSID: '', accountSID: '',
@@ -203,8 +207,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -6,7 +6,7 @@
/> />
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()"> <form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.channelName.$error }"> <label :class="{ error: v$.channelName.$error }">
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.LABEL') }} {{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.LABEL') }}
<input <input
v-model.trim="channelName" v-model.trim="channelName"
@@ -14,22 +14,22 @@
:placeholder=" :placeholder="
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.PLACEHOLDER') $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
" "
@blur="$v.channelName.$touch" @blur="v$.channelName.$touch"
/> />
<span v-if="$v.channelName.$error" class="message">{{ <span v-if="v$.channelName.$error" class="message">{{
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.ERROR') $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.ERROR')
}}</span> }}</span>
</label> </label>
</div> </div>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"> <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<label :class="{ error: $v.email.$error }"> <label :class="{ error: v$.email.$error }">
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.LABEL') }} {{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.LABEL') }}
<input <input
v-model.trim="email" v-model.trim="email"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.PLACEHOLDER')"
@blur="$v.email.$touch" @blur="v$.email.$touch"
/> />
</label> </label>
<p class="help-text"> <p class="help-text">
@@ -50,15 +50,19 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import { required, email } from 'vuelidate/lib/validators'; import { required, email } from '@vuelidate/validators';
import router from '../../../../../index'; import router from '../../../../../index';
import PageHeader from '../../../SettingsSubPageHeader.vue'; import PageHeader from '../../../SettingsSubPageHeader.vue';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
PageHeader, PageHeader,
}, },
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
channelName: '', channelName: '',
@@ -77,8 +81,8 @@ export default {
}, },
methods: { methods: {
async createChannel() { async createChannel() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -12,7 +12,7 @@
v-model.trim="email" v-model.trim="email"
type="text" type="text"
:placeholder="$t('INBOX_MGMT.ADD.MICROSOFT.EMAIL_PLACEHOLDER')" :placeholder="$t('INBOX_MGMT.ADD.MICROSOFT.EMAIL_PLACEHOLDER')"
@blur="$v.email.$touch" @blur="v$.email.$touch"
/> />
<woot-submit-button <woot-submit-button
icon="brand-twitter" icon="brand-twitter"
@@ -27,11 +27,15 @@
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import microsoftClient from 'dashboard/api/channel/microsoftClient'; import microsoftClient from 'dashboard/api/channel/microsoftClient';
import SettingsSubPageHeader from '../../../SettingsSubPageHeader.vue'; import SettingsSubPageHeader from '../../../SettingsSubPageHeader.vue';
import { required, email } from 'vuelidate/lib/validators'; import { required, email } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { SettingsSubPageHeader }, components: { SettingsSubPageHeader },
mixins: [alertMixin], mixins: [alertMixin],
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { email: '', isRequestingAuthorization: false }; return { email: '', isRequestingAuthorization: false };
}, },
@@ -41,8 +45,8 @@ export default {
methods: { methods: {
async requestAuthorization() { async requestAuthorization() {
try { try {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) return; if (this.v$.$invalid) return;
this.isRequestingAuthorization = true; this.isRequestingAuthorization = true;
const response = await microsoftClient.generateAuthorization({ const response = await microsoftClient.generateAuthorization({
@@ -105,7 +105,7 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~dashboard/assets/scss/variables'; @import 'dashboard/assets/scss/variables';
.fb--login { .fb--login {
img { img {
@@ -17,7 +17,7 @@
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')"
@select="$v.selectedAgents.$touch" @select="v$.selectedAgents.$touch"
/> />
<woot-submit-button <woot-submit-button
@@ -56,10 +56,10 @@
<woot-input <woot-input
v-model.trim="maxAssignmentLimit" v-model.trim="maxAssignmentLimit"
type="number" type="number"
:class="{ error: $v.maxAssignmentLimit.$error }" :class="{ error: v$.maxAssignmentLimit.$error }"
:error="maxAssignmentLimitErrors" :error="maxAssignmentLimitErrors"
:label="$t('INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT')" :label="$t('INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT')"
@blur="$v.maxAssignmentLimit.$touch" @blur="v$.maxAssignmentLimit.$touch"
/> />
<p class="pb-1 text-sm not-italic text-slate-600 dark:text-slate-400"> <p class="pb-1 text-sm not-italic text-slate-600 dark:text-slate-400">
@@ -68,7 +68,7 @@
<woot-submit-button <woot-submit-button
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')" :button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
:disabled="$v.maxAssignmentLimit.$invalid" :disabled="v$.maxAssignmentLimit.$invalid"
@click="updateInbox" @click="updateInbox"
/> />
</div> </div>
@@ -78,10 +78,11 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { minValue } from 'vuelidate/lib/validators'; import { minValue } from '@vuelidate/validators';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import configMixin from 'shared/mixins/configMixin'; import configMixin from 'shared/mixins/configMixin';
import SettingsSection from '../../../../../components/SettingsSection.vue'; import SettingsSection from '../../../../../components/SettingsSection.vue';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -94,6 +95,9 @@ export default {
default: () => ({}), default: () => ({}),
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
selectedAgents: [], selectedAgents: [],
@@ -107,7 +111,7 @@ export default {
agentList: 'agents/getAgents', agentList: 'agents/getAgents',
}), }),
maxAssignmentLimitErrors() { maxAssignmentLimitErrors() {
if (this.$v.maxAssignmentLimit.$error) { if (this.v$.maxAssignmentLimit.$error) {
return this.$t( return this.$t(
'INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT_RANGE_ERROR' 'INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT_RANGE_ERROR'
); );
@@ -191,8 +195,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';
.max-assignment-container { .max-assignment-container {
padding-top: var(--space-slab); padding-top: var(--space-slab);
@@ -141,7 +141,7 @@
" "
/> />
<woot-button <woot-button
:disabled="$v.whatsAppInboxAPIKey.$invalid" :disabled="v$.whatsAppInboxAPIKey.$invalid"
@click="updateWhatsAppInboxAPIKey" @click="updateWhatsAppInboxAPIKey"
> >
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_BUTTON') }} {{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_BUTTON') }}
@@ -159,7 +159,8 @@ import SettingsSection from '../../../../../components/SettingsSection.vue';
import ImapSettings from '../ImapSettings.vue'; import ImapSettings from '../ImapSettings.vue';
import SmtpSettings from '../SmtpSettings.vue'; import SmtpSettings from '../SmtpSettings.vue';
import MicrosoftReauthorize from '../channels/microsoft/Reauthorize.vue'; import MicrosoftReauthorize from '../channels/microsoft/Reauthorize.vue';
import { required } from 'vuelidate/lib/validators'; import { required } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -175,6 +176,9 @@ export default {
default: () => ({}), default: () => ({}),
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
hmacMandatory: false, hmacMandatory: false,
@@ -247,6 +251,7 @@ export default {
.input { .input {
flex: 1; flex: 1;
margin-right: var(--space-small); margin-right: var(--space-small);
::v-deep input { ::v-deep input {
margin-bottom: 0; margin-bottom: 0;
} }
@@ -6,40 +6,40 @@
<form class="mx-0 flex flex-wrap" @submit.prevent="submit"> <form class="mx-0 flex flex-wrap" @submit.prevent="submit">
<woot-input <woot-input
v-model.trim="app.title" v-model.trim="app.title"
:class="{ error: $v.app.title.$error }" :class="{ error: v$.app.title.$error }"
class="w-full" class="w-full"
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_LABEL')" :label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_LABEL')"
:placeholder=" :placeholder="
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_PLACEHOLDER') $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_PLACEHOLDER')
" "
:error=" :error="
$v.app.title.$error v$.app.title.$error
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_ERROR') ? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_ERROR')
: null : null
" "
data-testid="app-title" data-testid="app-title"
@input="$v.app.title.$touch" @input="v$.app.title.$touch"
/> />
<woot-input <woot-input
v-model.trim="app.content.url" v-model.trim="app.content.url"
:class="{ error: $v.app.content.url.$error }" :class="{ error: v$.app.content.url.$error }"
class="w-full" class="w-full"
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_LABEL')" :label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_LABEL')"
:placeholder=" :placeholder="
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_PLACEHOLDER') $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_PLACEHOLDER')
" "
:error=" :error="
$v.app.content.url.$error v$.app.content.url.$error
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_ERROR') ? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_ERROR')
: null : null
" "
data-testid="app-url" data-testid="app-url"
@input="$v.app.content.url.$touch" @input="v$.app.content.url.$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">
<woot-button <woot-button
:is-loading="isLoading" :is-loading="isLoading"
:is-disabled="$v.$invalid" :is-disabled="v$.$invalid"
data-testid="label-submit" data-testid="label-submit"
> >
{{ submitButtonLabel }} {{ submitButtonLabel }}
@@ -54,8 +54,9 @@
</template> </template>
<script> <script>
import { required, url } from 'vuelidate/lib/validators'; import { required, url } 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],
@@ -73,6 +74,9 @@ export default {
default: () => ({}), default: () => ({}),
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
validations: { validations: {
app: { app: {
title: { required }, title: { required },
@@ -121,8 +125,8 @@ export default {
}, },
async submit() { async submit() {
try { try {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) { if (this.v$.$invalid) {
return; return;
} }
@@ -1,20 +1,20 @@
<template> <template>
<form class="flex flex-col w-full" @submit.prevent="onSubmit"> <form class="flex flex-col w-full" @submit.prevent="onSubmit">
<div class="w-full"> <div class="w-full">
<label :class="{ error: $v.url.$error }"> <label :class="{ error: v$.url.$error }">
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.LABEL') }} {{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.LABEL') }}
<input <input
v-model.trim="url" v-model.trim="url"
type="text" type="text"
name="url" name="url"
:placeholder="webhookURLInputPlaceholder" :placeholder="webhookURLInputPlaceholder"
@input="$v.url.$touch" @input="v$.url.$touch"
/> />
<span v-if="$v.url.$error" class="message"> <span v-if="v$.url.$error" class="message">
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.ERROR') }} {{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.ERROR') }}
</span> </span>
</label> </label>
<label :class="{ error: $v.url.$error }" class="mb-2"> <label :class="{ error: v$.url.$error }" class="mb-2">
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.LABEL') }} {{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.LABEL') }}
</label> </label>
<div v-for="event in supportedWebhookEvents" :key="event"> <div v-for="event in supportedWebhookEvents" :key="event">
@@ -35,7 +35,7 @@
<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">
<div class="w-full"> <div class="w-full">
<woot-button <woot-button
:disabled="$v.$invalid || isSubmitting" :disabled="v$.$invalid || isSubmitting"
:is-loading="isSubmitting" :is-loading="isSubmitting"
> >
{{ submitLabel }} {{ submitLabel }}
@@ -49,9 +49,10 @@
</template> </template>
<script> <script>
import { required, url, minLength } from 'vuelidate/lib/validators'; import { required, url, minLength } from '@vuelidate/validators';
import webhookMixin from './webhookMixin'; import webhookMixin from './webhookMixin';
import wootConstants from 'dashboard/constants/globals'; import wootConstants from 'dashboard/constants/globals';
import { useVuelidate } from '@vuelidate/core';
const { EXAMPLE_WEBHOOK_URL } = wootConstants; const { EXAMPLE_WEBHOOK_URL } = wootConstants;
@@ -82,6 +83,9 @@ export default {
required: true, required: true,
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
validations: { validations: {
url: { url: {
required, required,
@@ -7,23 +7,23 @@
<form class="mx-0 flex flex-wrap" @submit.prevent="addLabel"> <form class="mx-0 flex flex-wrap" @submit.prevent="addLabel">
<woot-input <woot-input
v-model.trim="title" v-model.trim="title"
:class="{ error: $v.title.$error }" :class="{ error: v$.title.$error }"
class="w-full label-name--input" class="w-full label-name--input"
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')" :label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')" :placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
:error="getLabelTitleErrorMessage" :error="getLabelTitleErrorMessage"
data-testid="label-title" data-testid="label-title"
@input="$v.title.$touch" @input="v$.title.$touch"
/> />
<woot-input <woot-input
v-model.trim="description" v-model.trim="description"
:class="{ error: $v.description.$error }" :class="{ error: v$.description.$error }"
class="w-full" class="w-full"
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')" :label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')" :placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
data-testid="label-description" data-testid="label-description"
@input="$v.description.$touch" @input="v$.description.$touch"
/> />
<div class="w-full"> <div class="w-full">
@@ -40,7 +40,7 @@
</div> </div>
<div class="flex justify-end items-center py-2 px-0 gap-2 w-full"> <div class="flex justify-end items-center py-2 px-0 gap-2 w-full">
<woot-button <woot-button
:is-disabled="$v.title.$invalid || uiFlags.isCreating" :is-disabled="v$.title.$invalid || uiFlags.isCreating"
:is-loading="uiFlags.isCreating" :is-loading="uiFlags.isCreating"
data-testid="label-submit" data-testid="label-submit"
> >
@@ -4,20 +4,20 @@
<form class="mx-0 flex flex-wrap" @submit.prevent="editLabel"> <form class="mx-0 flex flex-wrap" @submit.prevent="editLabel">
<woot-input <woot-input
v-model.trim="title" v-model.trim="title"
:class="{ error: $v.title.$error }" :class="{ error: v$.title.$error }"
class="w-full label-name--input" class="w-full label-name--input"
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')" :label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')" :placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
:error="getLabelTitleErrorMessage" :error="getLabelTitleErrorMessage"
@input="$v.title.$touch" @input="v$.title.$touch"
/> />
<woot-input <woot-input
v-model.trim="description" v-model.trim="description"
:class="{ error: $v.description.$error }" :class="{ error: v$.description.$error }"
class="w-full" class="w-full"
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')" :label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')" :placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
@input="$v.description.$touch" @input="v$.description.$touch"
/> />
<div class="w-full"> <div class="w-full">
@@ -34,7 +34,7 @@
</div> </div>
<div class="flex justify-end items-center py-2 px-0 gap-2 w-full"> <div class="flex justify-end items-center py-2 px-0 gap-2 w-full">
<woot-button <woot-button
:is-disabled="$v.title.$invalid || uiFlags.isUpdating" :is-disabled="v$.title.$invalid || uiFlags.isUpdating"
:is-loading="uiFlags.isUpdating" :is-loading="uiFlags.isUpdating"
> >
{{ $t('LABEL_MGMT.FORM.EDIT') }} {{ $t('LABEL_MGMT.FORM.EDIT') }}
@@ -188,7 +188,7 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~dashboard/assets/scss/variables'; @import 'dashboard/assets/scss/variables';
.label-color--container { .label-color--container {
@apply flex items-center; @apply flex items-center;
@@ -197,6 +197,7 @@ export default {
.label-color--display { .label-color--display {
@apply rounded h-4 w-4 mr-1 rtl:mr-0 rtl:ml-1 border border-solid border-slate-50 dark:border-slate-700; @apply rounded h-4 w-4 mr-1 rtl:mr-0 rtl:ml-1 border border-solid border-slate-50 dark:border-slate-700;
} }
.label-title { .label-title {
span { span {
@apply w-60 inline-block; @apply w-60 inline-block;
@@ -1,6 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueI18n from 'vue-i18n'; import VueI18n from 'vue-i18n';
import Vuelidate from 'vuelidate';
import validationMixin from '../validationMixin'; import validationMixin from '../validationMixin';
import validations from '../validations'; import validations from '../validations';
@@ -8,7 +7,6 @@ import i18n from 'dashboard/i18n';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueI18n); localVue.use(VueI18n);
localVue.use(Vuelidate);
const i18nConfig = new VueI18n({ const i18nConfig = new VueI18n({
locale: 'en', locale: 'en',
messages: i18n, messages: i18n,
@@ -29,7 +27,7 @@ describe('validationMixin', () => {
return { title: 'sales' }; return { title: 'sales' };
}, },
}); });
wrapper.vm.$v.$touch(); wrapper.vm.v$.$touch();
expect(wrapper.vm.getLabelTitleErrorMessage).toBe(''); expect(wrapper.vm.getLabelTitleErrorMessage).toBe('');
}); });
it('it should return label required error message if empty name is passed', async () => { it('it should return label required error message if empty name is passed', async () => {
@@ -40,7 +38,7 @@ describe('validationMixin', () => {
return { title: '' }; return { title: '' };
}, },
}); });
wrapper.vm.$v.$touch(); wrapper.vm.v$.$touch();
expect(wrapper.vm.getLabelTitleErrorMessage).toBe('Label name is required'); expect(wrapper.vm.getLabelTitleErrorMessage).toBe('Label name is required');
}); });
it('it should return label minimum length error message if one charceter label name is passed', async () => { it('it should return label minimum length error message if one charceter label name is passed', async () => {
@@ -51,7 +49,7 @@ describe('validationMixin', () => {
return { title: 's' }; return { title: 's' };
}, },
}); });
wrapper.vm.$v.$touch(); wrapper.vm.v$.$touch();
expect(wrapper.vm.getLabelTitleErrorMessage).toBe( expect(wrapper.vm.getLabelTitleErrorMessage).toBe(
'Minimum length 2 is required' 'Minimum length 2 is required'
); );
@@ -64,7 +62,7 @@ describe('validationMixin', () => {
return { title: 'sales enquiry' }; return { title: 'sales enquiry' };
}, },
}); });
wrapper.vm.$v.$touch(); wrapper.vm.v$.$touch();
expect(wrapper.vm.getLabelTitleErrorMessage).toBe( expect(wrapper.vm.getLabelTitleErrorMessage).toBe(
'Only Alphabets, Numbers, Hyphen and Underscore are allowed' 'Only Alphabets, Numbers, Hyphen and Underscore are allowed'
); );
@@ -2,13 +2,13 @@ export default {
computed: { computed: {
getLabelTitleErrorMessage() { getLabelTitleErrorMessage() {
let errorMessage = ''; let errorMessage = '';
if (!this.$v.title.$error) { if (!this.v$.title.$error) {
errorMessage = ''; errorMessage = '';
} else if (!this.$v.title.required) { } else if (!this.v$.title.required) {
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.REQUIRED_ERROR'); errorMessage = this.$t('LABEL_MGMT.FORM.NAME.REQUIRED_ERROR');
} else if (!this.$v.title.minLength) { } else if (!this.v$.title.minLength) {
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR'); errorMessage = this.$t('LABEL_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR');
} else if (!this.$v.title.validLabelCharacters) { } else if (!this.v$.title.validLabelCharacters) {
errorMessage = this.$t('LABEL_MGMT.FORM.NAME.VALID_ERROR'); errorMessage = this.$t('LABEL_MGMT.FORM.NAME.VALID_ERROR');
} }
return errorMessage; return errorMessage;
@@ -1,4 +1,4 @@
import { required, minLength } from 'vuelidate/lib/validators'; import { required, minLength } from '@vuelidate/validators';
export const validLabelCharacters = (str = '') => !!str && !str.includes(' '); export const validLabelCharacters = (str = '') => !!str && !str.includes(' ');
@@ -26,7 +26,8 @@
<script> <script>
import MacroNodes from './MacroNodes.vue'; import MacroNodes from './MacroNodes.vue';
import MacroProperties from './MacroProperties.vue'; import MacroProperties from './MacroProperties.vue';
import { required, requiredIf } from 'vuelidate/lib/validators'; import { required, requiredIf } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
export default { export default {
components: { components: {
@@ -44,6 +45,9 @@ export default {
default: () => ({}), default: () => ({}),
}, },
}, },
setup() {
return { v$: useVuelidate() };
},
data() { data() {
return { return {
macro: this.macroData, macro: this.macroData,
@@ -112,16 +116,16 @@ export default {
this.macro.actions.splice(index, 1); this.macro.actions.splice(index, 1);
}, },
submit() { submit() {
this.$v.$touch(); this.v$.$touch();
if (this.$v.$invalid) return; if (this.v$.$invalid) return;
this.$emit('submit', this.macro); this.$emit('submit', this.macro);
}, },
resetNode(index) { resetNode(index) {
this.$v.macro.actions.$each[index].$reset(); this.v$.macro.actions.$each[index].$reset();
this.macro.actions[index].action_params = []; this.macro.actions[index].action_params = [];
}, },
resetValidation() { resetValidation() {
this.$v.$reset(); this.v$.$reset();
}, },
}, },
}; };
@@ -129,13 +133,16 @@ export default {
<style scoped> <style scoped>
@tailwind components; @tailwind components;
@layer components { @layer components {
.macro-gradient-radial { .macro-gradient-radial {
background-image: radial-gradient(#ebf0f5 1.2px, transparent 0); background-image: radial-gradient(#ebf0f5 1.2px, transparent 0);
} }
.macro-dark-gradient-radial { .macro-dark-gradient-radial {
background-image: radial-gradient(#293f51 1.2px, transparent 0); background-image: radial-gradient(#293f51 1.2px, transparent 0);
} }
.macro-gradient-radial-size { .macro-gradient-radial-size {
background-size: 1rem 1rem; background-size: 1rem 1rem;
} }
@@ -11,7 +11,7 @@
<div <div
class="macro__node-action-item" class="macro__node-action-item"
:class="{ :class="{
'has-error': hasError($v.macro.actions.$each[index]), 'has-error': hasError(v$.macro.actions.$each[index]),
}" }"
> >
<action-input <action-input
@@ -21,7 +21,7 @@
:show-action-input="showActionInput" :show-action-input="showActionInput"
:show-remove-button="false" :show-remove-button="false"
:is-macro="true" :is-macro="true"
:v="$v.macro.actions.$each[index]" :v="v$.macro.actions.$each[index]"
:initial-file-name="fileName" :initial-file-name="fileName"
@resetAction="$emit('resetAction')" @resetAction="$emit('resetAction')"
/> />
@@ -108,6 +108,7 @@ export default {
.macros__node-drag-handle { .macros__node-drag-handle {
@apply cursor-move -left-8 absolute; @apply cursor-move -left-8 absolute;
} }
.macro__node-action-container { .macro__node-action-container {
@apply w-full min-w-0 basis-full items-center flex relative; @apply w-full min-w-0 basis-full items-center flex relative;
@@ -125,15 +126,19 @@ export default {
0% { 0% {
transform: translateX(0); transform: translateX(0);
} }
25% { 25% {
transform: translateX(0.234375rem); transform: translateX(0.234375rem);
} }
50% { 50% {
transform: translateX(-0.234375rem); transform: translateX(-0.234375rem);
} }
75% { 75% {
transform: translateX(0.234375rem); transform: translateX(0.234375rem);
} }
100% { 100% {
transform: translateX(0); transform: translateX(0);
} }
@@ -7,8 +7,8 @@
:value="macroName" :value="macroName"
:label="$t('MACROS.ADD.FORM.NAME.LABEL')" :label="$t('MACROS.ADD.FORM.NAME.LABEL')"
:placeholder="$t('MACROS.ADD.FORM.NAME.PLACEHOLDER')" :placeholder="$t('MACROS.ADD.FORM.NAME.PLACEHOLDER')"
:error="$v.macro.name.$error ? $t('MACROS.ADD.FORM.NAME.ERROR') : null" :error="v$.macro.name.$error ? $t('MACROS.ADD.FORM.NAME.ERROR') : null"
:class="{ error: $v.macro.name.$error }" :class="{ error: v$.macro.name.$error }"
@input="onUpdateName($event)" @input="onUpdateName($event)"
/> />
</div> </div>

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