parent
bd11b2ec58
commit
85514cae8d
43 changed files with 707 additions and 345 deletions
|
@ -79,7 +79,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
|
|||
|
||||
def permitted_params
|
||||
params.permit(:id, :avatar, :name, :greeting_message, :greeting_enabled, channel:
|
||||
[:type, :website_url, :widget_color, :welcome_title, :welcome_tagline, :webhook_url, :email])
|
||||
[:type, :website_url, :widget_color, :welcome_title, :welcome_tagline, :webhook_url, :email, :reply_time])
|
||||
end
|
||||
|
||||
def inbox_update_params
|
||||
|
@ -91,6 +91,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
|
|||
:welcome_tagline,
|
||||
:webhook_url,
|
||||
:email,
|
||||
:reply_time,
|
||||
{ selected_feature_flags: [] }
|
||||
])
|
||||
end
|
||||
|
|
|
@ -4,10 +4,12 @@ class Api::V1::Widget::BaseController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def conversations
|
||||
@conversations = @contact_inbox.conversations.where(inbox_id: auth_token_params[:inbox_id])
|
||||
end
|
||||
|
||||
def conversation
|
||||
@conversation ||= @contact_inbox.conversations.where(
|
||||
inbox_id: auth_token_params[:inbox_id]
|
||||
).last
|
||||
@conversation ||= conversations.last
|
||||
end
|
||||
|
||||
def auth_token_params
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
.button {
|
||||
font-family: $body-font-family;
|
||||
font-weight: $font-weight-medium;
|
||||
|
|
|
@ -14,5 +14,4 @@
|
|||
@import '~bourbon/core/bourbon';
|
||||
|
||||
@include foundation-everything($flex: true);
|
||||
|
||||
@import 'woot';
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getContrastingTextColor } from 'shared/helpers/ColorHelper';
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
|
@ -43,12 +44,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
textColor() {
|
||||
const color = this.bgColor.replace('#', '');
|
||||
const r = parseInt(color.slice(0, 2), 16);
|
||||
const g = parseInt(color.slice(2, 4), 16);
|
||||
const b = parseInt(color.slice(4, 6), 16);
|
||||
// http://stackoverflow.com/a/3943023/112731
|
||||
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#FFFFFF';
|
||||
return getContrastingTextColor(this.bgColor);
|
||||
},
|
||||
labelClass() {
|
||||
return `label ${this.small ? 'small' : ''}`;
|
||||
|
|
|
@ -73,6 +73,13 @@
|
|||
"ENABLED": "Enabled",
|
||||
"DISABLED": "Disabled"
|
||||
},
|
||||
"REPLY_TIME": {
|
||||
"TITLE": "Set Reply time",
|
||||
"IN_A_FEW_MINUTES": "In a few minutes",
|
||||
"IN_A_FEW_HOURS": "In a few hours",
|
||||
"IN_A_DAY": "In a day",
|
||||
"HELP_TEXT": "This reply time will be displayed on the live chat widget"
|
||||
},
|
||||
"WIDGET_COLOR": {
|
||||
"LABEL": "Widget Color",
|
||||
"PLACEHOLDER": "Update the widget color used in widget"
|
||||
|
|
|
@ -78,8 +78,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
/* global bus */
|
||||
|
||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||
import Auth from '../../api/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="medium-12 columns text-center">
|
||||
<div class="website--code">
|
||||
<woot-code
|
||||
v-if="currentInbox.website_token"
|
||||
v-if="currentInbox.web_widget_script"
|
||||
:script="currentInbox.web_widget_script"
|
||||
>
|
||||
</woot-code>
|
||||
|
@ -75,7 +75,7 @@ export default {
|
|||
return this.$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE');
|
||||
}
|
||||
|
||||
if (!this.currentInbox.website_token) {
|
||||
if (!this.currentInbox.web_widget_script) {
|
||||
return this.$t('INBOX_MGMT.FINISH.MESSAGE');
|
||||
}
|
||||
return this.$t('INBOX_MGMT.FINISH.WEBSITE_SUCCESS');
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
}}
|
||||
</p>
|
||||
</label>
|
||||
|
||||
<woot-input
|
||||
v-if="greetingEnabled"
|
||||
v-model.trim="greetingMessage"
|
||||
|
@ -116,6 +117,30 @@
|
|||
)
|
||||
"
|
||||
/>
|
||||
|
||||
<label class="medium-9 columns">
|
||||
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.REPLY_TIME.TITLE') }}
|
||||
<select v-model="replyTime">
|
||||
<option key="in_a_few_minutes" value="in_a_few_minutes">
|
||||
{{
|
||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.REPLY_TIME.IN_A_FEW_MINUTES')
|
||||
}}
|
||||
</option>
|
||||
<option key="in_a_few_hours" value="in_a_few_hours">
|
||||
{{
|
||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.REPLY_TIME.IN_A_FEW_HOURS')
|
||||
}}
|
||||
</option>
|
||||
<option key="in_a_day" value="in_a_day">
|
||||
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.REPLY_TIME.IN_A_DAY') }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<p class="help-text">
|
||||
{{ $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.REPLY_TIME.HELP_TEXT') }}
|
||||
</p>
|
||||
</label>
|
||||
|
||||
<label class="medium-9 columns">
|
||||
{{ $t('INBOX_MGMT.SETTINGS_POPUP.AUTO_ASSIGNMENT') }}
|
||||
<select v-model="autoAssignment">
|
||||
|
@ -220,7 +245,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
/* eslint no-console: 0 */
|
||||
import { mapGetters } from 'vuex';
|
||||
import { createMessengerScript } from 'dashboard/helper/scriptGenerator';
|
||||
import configMixin from 'shared/mixins/configMixin';
|
||||
|
@ -249,6 +273,7 @@ export default {
|
|||
channelWelcomeTitle: '',
|
||||
channelWelcomeTagline: '',
|
||||
selectedFeatureFlags: [],
|
||||
replyTime: '',
|
||||
autoAssignmentOptions: [
|
||||
{
|
||||
value: true,
|
||||
|
@ -352,6 +377,7 @@ export default {
|
|||
this.channelWelcomeTitle = this.inbox.welcome_title;
|
||||
this.channelWelcomeTagline = this.inbox.welcome_tagline;
|
||||
this.selectedFeatureFlags = this.inbox.selected_feature_flags || [];
|
||||
this.replyTime = this.inbox.reply_time;
|
||||
});
|
||||
},
|
||||
async fetchAttachedAgents() {
|
||||
|
@ -364,7 +390,7 @@ export default {
|
|||
} = response;
|
||||
this.selectedAgents = inboxMembers;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// Handle error
|
||||
}
|
||||
},
|
||||
async updateAgents() {
|
||||
|
@ -395,6 +421,7 @@ export default {
|
|||
welcome_title: this.channelWelcomeTitle || '',
|
||||
welcome_tagline: this.channelWelcomeTagline || '',
|
||||
selectedFeatureFlags: this.selectedFeatureFlags,
|
||||
reply_time: this.replyTime || 'in_a_few_minutes',
|
||||
},
|
||||
};
|
||||
if (this.avatarFile) {
|
||||
|
@ -409,7 +436,6 @@ export default {
|
|||
handleImageUpload({ file, url }) {
|
||||
this.avatarFile = file;
|
||||
this.avatarUrl = url;
|
||||
console.log(this.avatarUrl);
|
||||
},
|
||||
},
|
||||
validations: {
|
||||
|
|
|
@ -6,3 +6,12 @@
|
|||
src: url('~shared/assets/fonts/Inter-Regular.woff2?v=3.11') format('woff2'),
|
||||
url('~shared/assets/fonts/Inter-Regular.woff?v=3.11') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('~shared/assets/fonts/Inter-Medium.woff2?v=3.11') format('woff2'),
|
||||
url('~shared/assets/fonts/Inter-Medium.woff?v=3.11') format('woff');
|
||||
}
|
||||
|
|
54
app/javascript/shared/components/Button.vue
Normal file
54
app/javascript/shared/components/Button.vue
Normal file
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<button :class="buttonClassName" :style="buttonStyles" @click="onClick">
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
block: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'blue',
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
buttonClassName() {
|
||||
let className = 'text-white py-3 px-4 rounded shadow-sm';
|
||||
if (this.type === 'blue' && !Object.keys(this.buttonStyles).length) {
|
||||
className = `${className} bg-woot-500 hover:bg-woot-700`;
|
||||
}
|
||||
if (this.block) {
|
||||
className = `${className} w-full`;
|
||||
}
|
||||
return className;
|
||||
},
|
||||
buttonStyles() {
|
||||
const styles = {};
|
||||
if (this.bgColor) {
|
||||
styles.backgroundColor = this.bgColor;
|
||||
}
|
||||
if (this.textColor) {
|
||||
styles.color = this.textColor;
|
||||
}
|
||||
return styles;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClick(e) {
|
||||
this.$emit('click', e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -22,7 +22,7 @@ export default {
|
|||
},
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: 3.2,
|
||||
default: 2,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
|
8
app/javascript/shared/helpers/ColorHelper.js
Normal file
8
app/javascript/shared/helpers/ColorHelper.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
export const getContrastingTextColor = bgColor => {
|
||||
const color = bgColor.replace('#', '');
|
||||
const r = parseInt(color.slice(0, 2), 16);
|
||||
const g = parseInt(color.slice(2, 4), 16);
|
||||
const b = parseInt(color.slice(4, 6), 16);
|
||||
// http://stackoverflow.com/a/3943023/112731
|
||||
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#FFFFFF';
|
||||
};
|
|
@ -1,31 +1,30 @@
|
|||
// Font sizes
|
||||
$font-size-nano: 0.8rem;
|
||||
$font-size-micro: 0.8rem;
|
||||
$font-size-mini: 1rem;
|
||||
$font-size-small: 1.2rem;
|
||||
$font-size-default: 1.4rem;
|
||||
$font-size-medium: 1.6rem;
|
||||
$font-size-large: 2rem;
|
||||
$font-size-big: 2.4rem;
|
||||
$font-size-bigger: 3.2rem;
|
||||
$font-size-mega: 4rem;
|
||||
$font-size-giga: 5.6rem;
|
||||
$font-size-micro: 0.5rem;
|
||||
$font-size-mini: 0.625rem;
|
||||
$font-size-small: 0.75rem;
|
||||
$font-size-default: 0.875rem;
|
||||
$font-size-medium: 1rem;
|
||||
$font-size-large: 1.25rem;
|
||||
$font-size-big: 1.5rem;
|
||||
$font-size-bigger: 2rem;
|
||||
$font-size-mega: 2.5rem;
|
||||
$font-size-giga: 3.5rem;
|
||||
|
||||
// spaces
|
||||
$zero: 0;
|
||||
$space-micro: 0.2rem;
|
||||
$space-smaller: 0.4rem;
|
||||
$space-small: 0.8rem;
|
||||
$space-one: 1rem;
|
||||
$space-slab: 1.2rem;
|
||||
$space-normal: 1.6rem;
|
||||
$space-two: 2rem;
|
||||
$space-medium: 2.4rem;
|
||||
$space-large: 3.2rem;
|
||||
$space-larger: 4.8rem;
|
||||
$space-big: 6.4rem;
|
||||
$space-jumbo: 8rem;
|
||||
$space-mega: 10rem;
|
||||
$space-micro: 0.125rem;
|
||||
$space-smaller: 0.25rem;
|
||||
$space-small: 0.5rem;
|
||||
$space-one: 0.625rem;
|
||||
$space-slab: 0.75rem;
|
||||
$space-normal: 1rem;
|
||||
$space-two: 1.25rem;
|
||||
$space-medium: 1.5rem;
|
||||
$space-large: 2rem;
|
||||
$space-larger: 3rem;
|
||||
$space-big: 4rem;
|
||||
$space-jumbo: 5rem;
|
||||
$space-mega: 6.25rem;
|
||||
|
||||
// font-weight
|
||||
$font-weight-feather: 100;
|
||||
|
@ -35,15 +34,6 @@ $font-weight-medium: 500;
|
|||
$font-weight-bold: 600;
|
||||
$font-weight-black: 700;
|
||||
|
||||
//Navbar
|
||||
$nav-bar-width: 23rem;
|
||||
$header-height: 5.6rem;
|
||||
|
||||
// Woot Logo
|
||||
$woot-logo-width: 20rem;
|
||||
$woot-logo-height: 8rem;
|
||||
$woot-logo-padding: $space-large $space-large $space-large $space-large;
|
||||
|
||||
// Colors
|
||||
$color-woot: #1f93ff;
|
||||
$color-primary: $color-woot;
|
||||
|
@ -65,20 +55,6 @@ $color-error: #ff382d;
|
|||
$color-primary-light: #c7e3ff;
|
||||
$color-primary-dark: darken($color-woot, 20%);
|
||||
|
||||
|
||||
// Thumbnail
|
||||
$thumbnail-radius: 4rem;
|
||||
|
||||
// chat-header
|
||||
$conv-header-height: 4rem;
|
||||
|
||||
// login
|
||||
|
||||
// Inbox List
|
||||
|
||||
$inbox-thumb-size: 4.8rem;
|
||||
|
||||
|
||||
// Spinner
|
||||
$spinkit-spinner-color: $color-white !default;
|
||||
$spinkit-spinner-margin: 0 0 0 1.6rem !default;
|
||||
|
@ -92,7 +68,7 @@ $swift-ease-out-duration: .4s !default;
|
|||
$swift-ease-out-timing-function: cubic-bezier(.25, .8, .25, 1) !default;
|
||||
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
|
||||
|
||||
$border-radius: 3px;
|
||||
$border-radius: 0.1875px;
|
||||
$line-height: 1;
|
||||
$footer-height: 11.2rem;
|
||||
$header-expanded-height: $space-medium * 10;
|
||||
|
@ -109,10 +85,6 @@ Arial,
|
|||
sans-serif;
|
||||
$ionicons-font-path: '~ionicons/fonts';
|
||||
|
||||
$spinkit-spinner-color: $color-white !default;
|
||||
$spinkit-spinner-margin: 0 0 0 1.6rem !default;
|
||||
$spinkit-size: 1.6rem !default;
|
||||
|
||||
// Break points
|
||||
$break-point-medium: 667px;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
@import 'reset';
|
||||
@import 'tailwindcss/base';
|
||||
@import 'tailwindcss/components';
|
||||
@import 'tailwindcss/utilities';
|
||||
@import 'variables';
|
||||
@import 'buttons';
|
||||
@import 'mixins';
|
||||
|
@ -10,7 +13,6 @@
|
|||
html,
|
||||
body {
|
||||
font-family: $font-family;
|
||||
font-size: 10px;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
height: 100%;
|
||||
|
|
|
@ -25,8 +25,8 @@ export default {
|
|||
@import '~widget/assets/scss/variables.scss';
|
||||
|
||||
.typing-bubble {
|
||||
max-width: $space-medium;
|
||||
padding: $space-smaller $space-small;
|
||||
max-width: $space-normal * 2.4;
|
||||
padding: $space-small;
|
||||
border-bottom-left-radius: $space-two;
|
||||
border-top-left-radius: $space-small;
|
||||
|
||||
|
|
|
@ -1,80 +1,27 @@
|
|||
<template>
|
||||
<div class="available-agents">
|
||||
<div class="toast-bg">
|
||||
<div class="avatars-wrap">
|
||||
<GroupedAvatars :users="users" />
|
||||
</div>
|
||||
<div class="title">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<grouped-avatars :users="users" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GroupedAvatars from 'widget/components/GroupedAvatars.vue';
|
||||
import agentMixin from '../mixins/agentMixin';
|
||||
|
||||
export default {
|
||||
name: 'AvailableAgents',
|
||||
components: { GroupedAvatars },
|
||||
mixins: [agentMixin],
|
||||
props: {
|
||||
agents: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
onClose: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
users() {
|
||||
return this.agents.map(agent => ({
|
||||
return this.agents.slice(0, 5).map(agent => ({
|
||||
id: agent.id,
|
||||
avatar: agent.avatar_url,
|
||||
name: agent.name,
|
||||
}));
|
||||
},
|
||||
title() {
|
||||
return this.getAvailableAgentsText(this.agents);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~widget/assets/scss/variables.scss';
|
||||
@import '~widget/assets/scss/mixins.scss';
|
||||
|
||||
.available-agents {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
margin: $space-normal $space-medium;
|
||||
box-sizing: border-box;
|
||||
|
||||
.toast-bg {
|
||||
border-radius: $space-large;
|
||||
background: $color-body;
|
||||
@include shadow-medium;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: $font-size-default;
|
||||
font-weight: $font-weight-medium;
|
||||
color: $color-white;
|
||||
padding: $space-small $space-normal $space-small $space-small;
|
||||
line-height: 1.4;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.avatars-wrap {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: $space-small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,27 @@
|
|||
<template>
|
||||
<header class="header-collapsed">
|
||||
<div class="header-branding">
|
||||
<img v-if="avatarUrl" :src="avatarUrl" alt="avatar" />
|
||||
<h2 class="title" v-html="title"></h2>
|
||||
<img
|
||||
v-if="avatarUrl"
|
||||
class="inbox--avatar mr-3"
|
||||
:src="avatarUrl"
|
||||
alt="avatar"
|
||||
/>
|
||||
<div>
|
||||
<div class="text-black-900 font-medium text-base flex items-center">
|
||||
<span class="mr-1" v-html="title" />
|
||||
<div
|
||||
:class="
|
||||
`status-view--badge rounded-full leading-4 ${
|
||||
availableAgents.length ? 'bg-green-500' : 'hidden'
|
||||
}`
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs mt-1 text-black-700">
|
||||
{{ replyTimeStatus }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<header-actions :show-popout-button="showPopoutButton" />
|
||||
</header>
|
||||
|
@ -11,11 +30,15 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import HeaderActions from './HeaderActions';
|
||||
import configMixin from 'widget/mixins/configMixin';
|
||||
import teamAvailabilityMixin from 'widget/mixins/teamAvailabilityMixin';
|
||||
|
||||
export default {
|
||||
name: 'ChatHeader',
|
||||
components: {
|
||||
HeaderActions,
|
||||
},
|
||||
mixins: [configMixin, teamAvailabilityMixin],
|
||||
props: {
|
||||
avatarUrl: {
|
||||
type: String,
|
||||
|
@ -29,6 +52,10 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
availableAgents: {
|
||||
type: Array,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
|
@ -48,7 +75,8 @@ export default {
|
|||
padding: $space-two $space-medium;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
color: $color-white;
|
||||
background: white;
|
||||
@include shadow-large;
|
||||
|
||||
.header-branding {
|
||||
display: flex;
|
||||
|
@ -60,15 +88,17 @@ export default {
|
|||
}
|
||||
|
||||
.title {
|
||||
font-size: $font-size-large;
|
||||
font-weight: $font-weight-medium;
|
||||
color: $color-heading;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: $space-small;
|
||||
.inbox--avatar {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.status-view--badge {
|
||||
height: $space-small;
|
||||
width: $space-small;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
<template>
|
||||
<header class="header-expanded">
|
||||
<div class="header--row">
|
||||
<header class="header-expanded py-8 px-6 bg-white relative box-border w-full">
|
||||
<div class="flex justify-between items-start">
|
||||
<img v-if="avatarUrl" class="logo" :src="avatarUrl" />
|
||||
<header-actions :show-popout-button="showPopoutButton" />
|
||||
</div>
|
||||
<h2 class="title" v-html="introHeading"></h2>
|
||||
<p class="body" v-html="introBody"></p>
|
||||
<h2
|
||||
class="text-slate-900 mt-6 text-4xl mb-3 font-normal"
|
||||
v-html="introHeading"
|
||||
/>
|
||||
<p class="text-lg text-black-700 leading-normal" v-html="introBody" />
|
||||
</header>
|
||||
</template>
|
||||
|
||||
|
@ -44,38 +47,14 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~widget/assets/scss/variables.scss';
|
||||
@import '~widget/assets/scss/mixins.scss';
|
||||
|
||||
.header-expanded {
|
||||
padding: $space-large $space-medium $space-large;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
@include shadow-large;
|
||||
|
||||
.logo {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $color-heading;
|
||||
font-size: $font-size-mega;
|
||||
font-weight: $font-weight-normal;
|
||||
margin-bottom: $space-slab;
|
||||
margin-top: $space-medium;
|
||||
}
|
||||
|
||||
.body {
|
||||
color: $color-body;
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.header--row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<button
|
||||
type="submit"
|
||||
:disabled="disabled"
|
||||
class="send-button"
|
||||
class="send-button ml-1"
|
||||
@click="onClick"
|
||||
>
|
||||
<i
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<template>
|
||||
<div class="avatars">
|
||||
<span v-for="user in users" :key="user.id" class="avatar">
|
||||
<Thumbnail
|
||||
size="24px"
|
||||
<div class="flex overflow-hidden">
|
||||
<span
|
||||
v-for="(user, index) in users"
|
||||
:key="user.id"
|
||||
:class="
|
||||
`${
|
||||
index ? '-ml-4' : ''
|
||||
} inline-block rounded-full text-white shadow-solid`
|
||||
"
|
||||
>
|
||||
<thumbnail
|
||||
size="40px"
|
||||
:username="user.name"
|
||||
:src="user.avatar"
|
||||
has-border
|
||||
|
@ -25,22 +33,3 @@ export default {
|
|||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~widget/assets/scss/variables.scss';
|
||||
@import '~widget/assets/scss/mixins.scss';
|
||||
|
||||
.avatars {
|
||||
display: inline-block;
|
||||
padding-left: $space-one;
|
||||
|
||||
.avatar {
|
||||
margin-left: -$space-slab;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
width: $space-medium;
|
||||
height: $space-medium;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="isIframe" class="actions">
|
||||
<div v-if="isIframe" class="actions flex items-center">
|
||||
<button
|
||||
v-if="showPopoutButton"
|
||||
class="button transparent compact new-window--button"
|
||||
|
@ -66,9 +66,6 @@ export default {
|
|||
@import '~widget/assets/scss/variables.scss';
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
margin-left: $space-normal;
|
||||
}
|
||||
|
|
59
app/javascript/widget/components/TeamAvailability.vue
Normal file
59
app/javascript/widget/components/TeamAvailability.vue
Normal file
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<div class="px-4">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="text-black-700">
|
||||
<div class="text-base leading-5 font-medium mb-1">
|
||||
{{ teamAvailabilityStatus }}
|
||||
</div>
|
||||
<div class="text-xs leading-4 mt-1">
|
||||
{{ replyTimeStatus }}
|
||||
</div>
|
||||
</div>
|
||||
<available-agents :agents="availableAgents" />
|
||||
</div>
|
||||
<woot-button
|
||||
class="font-medium"
|
||||
block
|
||||
:bg-color="widgetColor"
|
||||
:text-color="textColor"
|
||||
@click="startConversation"
|
||||
>
|
||||
{{ $t('START_CONVERSATION') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import AvailableAgents from 'widget/components/AvailableAgents.vue';
|
||||
import { getContrastingTextColor } from 'shared/helpers/ColorHelper';
|
||||
import WootButton from 'shared/components/Button';
|
||||
import configMixin from 'widget/mixins/configMixin';
|
||||
import teamAvailabilityMixin from 'widget/mixins/teamAvailabilityMixin';
|
||||
|
||||
export default {
|
||||
name: 'TeamAvailability',
|
||||
components: {
|
||||
AvailableAgents,
|
||||
WootButton,
|
||||
},
|
||||
mixins: [configMixin, teamAvailabilityMixin],
|
||||
props: {
|
||||
availableAgents: {
|
||||
type: Array,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({ widgetColor: 'appConfig/getWidgetColor' }),
|
||||
textColor() {
|
||||
return getContrastingTextColor(this.widgetColor);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
startConversation() {
|
||||
this.$emit('start-conversation');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -8,12 +8,16 @@
|
|||
"SUBMIT": "Submit"
|
||||
}
|
||||
},
|
||||
"AGENT_AVAILABILITY": {
|
||||
"IS_AVAILABLE": "is available",
|
||||
"ARE_AVAILABLE": "are available",
|
||||
"OTHERS_ARE_AVAILABLE": "others are available",
|
||||
"AND": "and"
|
||||
"TEAM_AVAILABILITY": {
|
||||
"ONLINE": "We are online",
|
||||
"OFFLINE": "We are offline"
|
||||
},
|
||||
"REPLY_TIME": {
|
||||
"IN_A_FEW_MINUTES": "Typically replies in a few minutes",
|
||||
"IN_A_FEW_HOURS": "Typically replies in a few hours",
|
||||
"IN_A_DAY": "Typically replies in a day"
|
||||
},
|
||||
"START_CONVERSATION": "Start Conversation",
|
||||
"UNREAD_VIEW": {
|
||||
"VIEW_MESSAGES_BUTTON": "See new messages",
|
||||
"CLOSE_MESSAGES_BUTTON": "Close"
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
export default {
|
||||
methods: {
|
||||
getAvailableAgentsText(agents) {
|
||||
const count = agents.length;
|
||||
if (count === 1) {
|
||||
const [agent] = agents;
|
||||
return `${agent.name} ${this.$t('AGENT_AVAILABILITY.IS_AVAILABLE')}`;
|
||||
}
|
||||
|
||||
if (count === 2) {
|
||||
const [first, second] = agents;
|
||||
return `${first.name} ${this.$t('AGENT_AVAILABILITY.AND')} ${
|
||||
second.name
|
||||
} ${this.$t('AGENT_AVAILABILITY.ARE_AVAILABLE')}`;
|
||||
}
|
||||
|
||||
const [agent] = agents;
|
||||
const rest = agents.length - 1;
|
||||
return `${agent.name} ${this.$t(
|
||||
'AGENT_AVAILABILITY.AND'
|
||||
)} ${rest} ${this.$t('AGENT_AVAILABILITY.OTHERS_ARE_AVAILABLE')}`;
|
||||
},
|
||||
},
|
||||
};
|
|
@ -21,5 +21,20 @@ export default {
|
|||
hasAttachmentsEnabled() {
|
||||
return this.channelConfig.enabledFeatures.includes('attachments');
|
||||
},
|
||||
replyTime() {
|
||||
return window.chatwootWebChannel.replyTime;
|
||||
},
|
||||
replyTimeStatus() {
|
||||
switch (this.replyTime) {
|
||||
case 'in_a_few_minutes':
|
||||
return this.$t('REPLY_TIME.IN_A_FEW_MINUTES');
|
||||
case 'in_a_few_hours':
|
||||
return this.$t('REPLY_TIME.IN_A_FEW_HOURS');
|
||||
case 'in_a_day':
|
||||
return this.$t('REPLY_TIME.IN_A_DAY');
|
||||
default:
|
||||
return this.$t('REPLY_TIME.IN_A_FEW_HOURS');
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
import { createWrapper } from '@vue/test-utils';
|
||||
import agentMixin from '../agentMixin';
|
||||
import Vue from 'vue';
|
||||
|
||||
const translations = {
|
||||
'AGENT_AVAILABILITY.IS_AVAILABLE': 'is available',
|
||||
'AGENT_AVAILABILITY.ARE_AVAILABLE': 'are available',
|
||||
'AGENT_AVAILABILITY.OTHERS_ARE_AVAILABLE': 'others are available',
|
||||
'AGENT_AVAILABILITY.AND': 'and',
|
||||
};
|
||||
|
||||
const TestComponent = {
|
||||
render() {},
|
||||
title: 'TestComponent',
|
||||
mixins: [agentMixin],
|
||||
methods: {
|
||||
$t(key) {
|
||||
return translations[key];
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('agentMixin', () => {
|
||||
test('returns correct text', () => {
|
||||
const Constructor = Vue.extend(TestComponent);
|
||||
const vm = new Constructor().$mount();
|
||||
const wrapper = createWrapper(vm);
|
||||
|
||||
expect(wrapper.vm.getAvailableAgentsText([{ name: 'Pranav' }])).toEqual(
|
||||
'Pranav is available'
|
||||
);
|
||||
|
||||
expect(
|
||||
wrapper.vm.getAvailableAgentsText([
|
||||
{ name: 'Pranav' },
|
||||
{ name: 'Nithin' },
|
||||
])
|
||||
).toEqual('Pranav and Nithin are available');
|
||||
|
||||
expect(
|
||||
wrapper.vm.getAvailableAgentsText([
|
||||
{ name: 'Pranav' },
|
||||
{ name: 'Nithin' },
|
||||
{ name: 'Subin' },
|
||||
{ name: 'Sojan' },
|
||||
])
|
||||
).toEqual('Pranav and 3 others are available');
|
||||
});
|
||||
});
|
10
app/javascript/widget/mixins/teamAvailabilityMixin.js
Normal file
10
app/javascript/widget/mixins/teamAvailabilityMixin.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
export default {
|
||||
computed: {
|
||||
teamAvailabilityStatus() {
|
||||
if (this.availableAgents.length) {
|
||||
return this.$t('TEAM_AVAILABILITY.ONLINE');
|
||||
}
|
||||
return this.$t('TEAM_AVAILABILITY.OFFLINE');
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,26 +1,55 @@
|
|||
<template>
|
||||
<div class="home">
|
||||
<div
|
||||
v-if="!conversationSize && isFetchingList"
|
||||
class="flex flex-1 items-center h-full bg-black-25 justify-center"
|
||||
>
|
||||
<spinner size=""></spinner>
|
||||
</div>
|
||||
<div v-else class="home">
|
||||
<div class="header-wrap">
|
||||
<ChatHeaderExpanded
|
||||
v-if="isHeaderExpanded && !hideWelcomeHeader"
|
||||
:intro-heading="introHeading"
|
||||
:intro-body="introBody"
|
||||
:avatar-url="channelConfig.avatarUrl"
|
||||
:show-popout-button="showPopoutButton"
|
||||
/>
|
||||
<ChatHeader
|
||||
v-else
|
||||
:title="channelConfig.websiteName"
|
||||
:avatar-url="channelConfig.avatarUrl"
|
||||
:show-popout-button="showPopoutButton"
|
||||
/>
|
||||
<transition
|
||||
enter-active-class="transition-all delay-200 duration-300 ease"
|
||||
leave-active-class="transition-all duration-200 ease-in"
|
||||
enter-class="opacity-0 transform -translate-y-32"
|
||||
enter-to-class="opacity-100 transform translate-y-0"
|
||||
leave-class="opacity-100 transform translate-y-0"
|
||||
leave-to-class="opacity-0 transform -translate-y-32"
|
||||
>
|
||||
<chat-header-expanded
|
||||
v-if="!isOnMessageView"
|
||||
:intro-heading="introHeading"
|
||||
:intro-body="introBody"
|
||||
:avatar-url="channelConfig.avatarUrl"
|
||||
:show-popout-button="showPopoutButton"
|
||||
/>
|
||||
<chat-header
|
||||
v-if="isOnMessageView"
|
||||
:title="channelConfig.websiteName"
|
||||
:avatar-url="channelConfig.avatarUrl"
|
||||
:show-popout-button="showPopoutButton"
|
||||
:available-agents="availableAgents"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<AvailableAgents v-if="showAvailableAgents" :agents="availableAgents" />
|
||||
<ConversationWrap :grouped-messages="groupedMessages" />
|
||||
<conversation-wrap :grouped-messages="groupedMessages" />
|
||||
<div class="footer-wrap">
|
||||
<div v-if="showInputTextArea" class="input-wrap">
|
||||
<ChatFooter />
|
||||
</div>
|
||||
<transition
|
||||
enter-active-class="transition-all delay-300 duration-300 ease"
|
||||
leave-active-class="transition-all duration-200 ease-in"
|
||||
enter-class="opacity-0 transform translate-y-32"
|
||||
enter-to-class="opacity-100 transform translate-y-0"
|
||||
leave-class="opacity-100 transform translate-y-0"
|
||||
leave-to-class="opacity-0 transform translate-y-32 "
|
||||
>
|
||||
<div v-if="showInputTextArea && isOnMessageView" class="input-wrap">
|
||||
<chat-footer />
|
||||
</div>
|
||||
<team-availability
|
||||
v-if="!isOnMessageView"
|
||||
:available-agents="availableAgents"
|
||||
@start-conversation="startConversation"
|
||||
/>
|
||||
</transition>
|
||||
<branding></branding>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,18 +61,21 @@ import ChatFooter from 'widget/components/ChatFooter.vue';
|
|||
import ChatHeaderExpanded from 'widget/components/ChatHeaderExpanded.vue';
|
||||
import ChatHeader from 'widget/components/ChatHeader.vue';
|
||||
import ConversationWrap from 'widget/components/ConversationWrap.vue';
|
||||
import AvailableAgents from 'widget/components/AvailableAgents.vue';
|
||||
import configMixin from '../mixins/configMixin';
|
||||
import TeamAvailability from 'widget/components/TeamAvailability';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: {
|
||||
Branding,
|
||||
ChatFooter,
|
||||
ChatHeader,
|
||||
ChatHeaderExpanded,
|
||||
ConversationWrap,
|
||||
ChatHeader,
|
||||
Branding,
|
||||
AvailableAgents,
|
||||
Spinner,
|
||||
TeamAvailability,
|
||||
},
|
||||
mixins: [configMixin],
|
||||
props: {
|
||||
|
@ -67,16 +99,20 @@ export default {
|
|||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
unreadMessageCount: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
showPopoutButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showMessageView: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isFetchingList: 'conversation/getIsFetchingList',
|
||||
}),
|
||||
isOpen() {
|
||||
return this.conversationAttributes.status === 'open';
|
||||
},
|
||||
|
@ -89,12 +125,18 @@ export default {
|
|||
}
|
||||
return true;
|
||||
},
|
||||
isOnMessageView() {
|
||||
if (this.hideWelcomeHeader) {
|
||||
return true;
|
||||
}
|
||||
if (this.conversationSize === 0) {
|
||||
return this.showMessageView;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
isHeaderExpanded() {
|
||||
return this.conversationSize === 0;
|
||||
},
|
||||
showAvailableAgents() {
|
||||
return this.availableAgents.length > 0 && this.conversationSize < 1;
|
||||
},
|
||||
introHeading() {
|
||||
return this.channelConfig.welcomeTitle;
|
||||
},
|
||||
|
@ -105,11 +147,16 @@ export default {
|
|||
return !(this.introHeading || this.introBody);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
startConversation() {
|
||||
this.showMessageView = !this.showMessageView;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~widget/assets/scss/woot.scss';
|
||||
@import '~widget/assets/scss/variables';
|
||||
|
||||
.home {
|
||||
width: 100%;
|
||||
|
@ -117,14 +164,13 @@ export default {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
background: $color-background;
|
||||
|
||||
.header-wrap {
|
||||
flex-shrink: 0;
|
||||
border-radius: $space-normal $space-normal $space-small $space-small;
|
||||
background: white;
|
||||
z-index: 99;
|
||||
@include shadow-large;
|
||||
|
||||
@media only screen and (min-device-width: 320px) and (max-device-width: 667px) {
|
||||
border-radius: 0;
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
/* global bus */
|
||||
|
||||
import { IFrameHelper } from 'widget/helpers/utils';
|
||||
import AgentBubble from 'widget/components/AgentMessageBubble.vue';
|
||||
import configMixin from '../mixins/configMixin';
|
||||
|
@ -94,7 +92,8 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '~widget/assets/scss/woot.scss';
|
||||
@import '~widget/assets/scss/variables';
|
||||
|
||||
.unread-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -148,7 +147,7 @@ export default {
|
|||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~widget/assets/scss/woot.scss';
|
||||
@import '~widget/assets/scss/variables';
|
||||
|
||||
.unread-messages {
|
||||
width: 100%;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# id :integer not null, primary key
|
||||
# feature_flags :integer default(3), not null
|
||||
# reply_time :integer default(0)
|
||||
# website_token :string
|
||||
# website_url :string
|
||||
# welcome_tagline :string
|
||||
|
@ -32,6 +33,7 @@ class Channel::WebWidget < ApplicationRecord
|
|||
has_flags 1 => :attachments,
|
||||
2 => :emoji_picker,
|
||||
:column => 'feature_flags'
|
||||
enum reply_time: { in_a_few_minutes: 0, in_a_few_hours: 1, in_a_day: 2 }
|
||||
|
||||
def name
|
||||
'Website'
|
||||
|
|
|
@ -19,7 +19,7 @@ class MessageTemplates::HookExecutionService
|
|||
end
|
||||
|
||||
def should_send_greeting?
|
||||
first_message_from_contact? && conversation.inbox.greeting_enabled?
|
||||
first_message_from_contact? && conversation.inbox.greeting_enabled? && conversation.inbox.greeting_message.present?
|
||||
end
|
||||
|
||||
def email_collect_was_sent?
|
||||
|
|
|
@ -17,10 +17,6 @@ class MessageTemplates::Template::Greeting
|
|||
|
||||
def greeting_message_params
|
||||
content = @conversation.inbox&.greeting_message
|
||||
if content.blank?
|
||||
content = I18n.t('conversations.templates.greeting_message_body',
|
||||
account_name: account.name)
|
||||
end
|
||||
|
||||
{
|
||||
account_id: @conversation.account_id,
|
||||
|
|
|
@ -15,4 +15,5 @@ json.web_widget_script resource.channel.try(:web_widget_script)
|
|||
json.forward_to_address resource.channel.try(:forward_to_address)
|
||||
json.phone_number resource.channel.try(:phone_number)
|
||||
json.selected_feature_flags resource.channel.try(:selected_feature_flags)
|
||||
json.reply_time resource.channel.try(:reply_time)
|
||||
json.reauthorization_required resource.channel.try(:reauthorization_required?) if resource.facebook?
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
window.chatwootSettings = {
|
||||
hideMessageBubble: false,
|
||||
position: 'left',
|
||||
locale: 'fr',
|
||||
locale: 'en',
|
||||
type: 'expanded_bubble',
|
||||
showPopoutButton: true,
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
widgetColor: '<%= @web_widget.widget_color %>',
|
||||
enabledFeatures: <%= @web_widget.selected_feature_flags.to_json.html_safe %>,
|
||||
enabledLanguages: <%= available_locales_with_name.to_json.html_safe %>,
|
||||
replyTime: '<%= @web_widget.reply_time %>'
|
||||
}
|
||||
window.chatwootWidgetDefaults = {
|
||||
useInboxAvatarForBot: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false)) %>,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddReplyTimeToWebWidget < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :channel_web_widgets, :reply_time, :integer, default: 0
|
||||
end
|
||||
end
|
|
@ -13,6 +13,7 @@
|
|||
ActiveRecord::Schema.define(version: 2020_10_11_152227) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
|
||||
|
@ -178,6 +179,7 @@ ActiveRecord::Schema.define(version: 2020_10_11_152227) do
|
|||
t.string "welcome_title"
|
||||
t.string "welcome_tagline"
|
||||
t.integer "feature_flags", default: 3, null: false
|
||||
t.integer "reply_time", default: 0
|
||||
t.index ["website_token"], name: "index_channel_web_widgets_on_website_token", unique: true
|
||||
end
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"md5": "^2.3.0",
|
||||
"query-string": "5",
|
||||
"spinkit": "~1.2.5",
|
||||
"tailwindcss": "^1.8.3",
|
||||
"tween.js": "~16.6.0",
|
||||
"url-loader": "^2.0.0",
|
||||
"v-tooltip": "~2.0.2",
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
/* eslint-disable */
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-import'),
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
require('postcss-import'),
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('tailwindcss'),
|
||||
require('autoprefixer'),
|
||||
],
|
||||
};
|
||||
|
|
|
@ -6,8 +6,8 @@ describe ::MessageTemplates::HookExecutionService do
|
|||
contact = create(:contact, email: nil)
|
||||
conversation = create(:conversation, contact: contact)
|
||||
|
||||
# ensure greeting hook is enabled
|
||||
conversation.inbox.update(greeting_enabled: true)
|
||||
# ensure greeting hook is enabled and greeting_message is present
|
||||
conversation.inbox.update(greeting_enabled: true, greeting_message: 'Hi, this is a greeting message')
|
||||
|
||||
email_collect_service = double
|
||||
greeting_service = double
|
||||
|
@ -24,5 +24,25 @@ describe ::MessageTemplates::HookExecutionService do
|
|||
expect(::MessageTemplates::Template::EmailCollect).to have_received(:new).with(conversation: message.conversation)
|
||||
expect(email_collect_service).to have_received(:perform)
|
||||
end
|
||||
|
||||
it 'doesnot calls ::MessageTemplates::Template::Greeting if greeting_message is empty' do
|
||||
contact = create(:contact, email: nil)
|
||||
conversation = create(:conversation, contact: contact)
|
||||
# ensure greeting hook is enabled
|
||||
conversation.inbox.update(greeting_enabled: true)
|
||||
|
||||
email_collect_service = double
|
||||
|
||||
allow(::MessageTemplates::Template::EmailCollect).to receive(:new).and_return(email_collect_service)
|
||||
allow(email_collect_service).to receive(:perform).and_return(true)
|
||||
allow(::MessageTemplates::Template::Greeting).to receive(:new)
|
||||
|
||||
# described class gets called in message after commit
|
||||
message = create(:message, conversation: conversation)
|
||||
|
||||
expect(::MessageTemplates::Template::Greeting).not_to have_received(:new)
|
||||
expect(::MessageTemplates::Template::EmailCollect).to have_received(:new).with(conversation: message.conversation)
|
||||
expect(email_collect_service).to have_received(:perform)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
91
tailwind.config.js
Normal file
91
tailwind.config.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
const { colors } = require('tailwindcss/defaultTheme');
|
||||
|
||||
module.exports = {
|
||||
purge: [
|
||||
'./app/javascript/widget/**/*.vue',
|
||||
'./app/javascript/shared/**/*.vue',
|
||||
],
|
||||
future: {
|
||||
removeDeprecatedGapUtilities: true,
|
||||
},
|
||||
theme: {
|
||||
colors: {
|
||||
white: colors.white,
|
||||
woot: {
|
||||
50: '#E3F2FF',
|
||||
100: '#BBDDFF',
|
||||
200: '#8FC9FF',
|
||||
300: '#61B3FF',
|
||||
400: '#3FA3FF',
|
||||
500: '#1F93FF',
|
||||
600: '#2284F0',
|
||||
700: '#2272DC',
|
||||
800: '#2161CA',
|
||||
900: '#1F41AB',
|
||||
},
|
||||
green: {
|
||||
50: '#E6F8E6',
|
||||
100: '#C4EEC2',
|
||||
200: '#9DE29A',
|
||||
300: '#6FD86F',
|
||||
400: '#44CE4B',
|
||||
500: '#00C41D',
|
||||
600: '#00B412',
|
||||
700: '#00A200',
|
||||
800: '#009000',
|
||||
900: '#007000',
|
||||
},
|
||||
yellow: {
|
||||
50: '#FFFEE8',
|
||||
100: '#FFFAC5',
|
||||
200: '#FFF69E',
|
||||
300: '#FEF176',
|
||||
400: '#FCEC56',
|
||||
500: '#F9E736',
|
||||
600: '#FFDD3A',
|
||||
700: '#FFC532',
|
||||
800: '#FDAD2A',
|
||||
900: '#F9841B',
|
||||
},
|
||||
slate: {
|
||||
50: '#F4F6FB',
|
||||
100: '#C8D6E6',
|
||||
200: '#ABBACE',
|
||||
300: '#8C9EB6',
|
||||
400: '#7489A4',
|
||||
500: '#5D7592',
|
||||
600: '#506781',
|
||||
700: '#40546B',
|
||||
800: '#314155',
|
||||
900: '#1F2D3D',
|
||||
},
|
||||
black: {
|
||||
50: '#F8F9FE',
|
||||
100: '#F2F3F7',
|
||||
200: '#E9EAEF',
|
||||
300: '#DADBDF',
|
||||
400: '#B6B7BB',
|
||||
500: '#96979C',
|
||||
600: '#6E6F73',
|
||||
700: '#3C4858',
|
||||
800: '#3C3D40',
|
||||
900: '#1B1C1F',
|
||||
},
|
||||
red: {
|
||||
50: '#FFEBEE',
|
||||
100: '#FFCCD1',
|
||||
200: '#F69898',
|
||||
300: '#EF6F6F',
|
||||
400: '#F94B4A',
|
||||
500: '#FF382D',
|
||||
600: '#F02B2D',
|
||||
700: '#DE1E27',
|
||||
800: '#D11320',
|
||||
900: '#C30011',
|
||||
},
|
||||
},
|
||||
extend: {},
|
||||
},
|
||||
variants: {},
|
||||
plugins: [],
|
||||
};
|
214
yarn.lock
214
yarn.lock
|
@ -914,6 +914,14 @@
|
|||
debug "^3.1.0"
|
||||
lodash.once "^4.1.1"
|
||||
|
||||
"@fullhuman/postcss-purgecss@^2.1.2":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz#50a954757ec78696615d3e118e3fee2d9291882e"
|
||||
integrity sha512-qnKm5dIOyPGJ70kPZ5jiz0I9foVOic0j+cOzNDoo8KoCf6HjicIZ99UfO2OmE7vCYSKAAepEwJtNzpiiZAh9xw==
|
||||
dependencies:
|
||||
postcss "7.0.32"
|
||||
purgecss "^2.3.0"
|
||||
|
||||
"@istanbuljs/load-nyc-config@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
|
||||
|
@ -1594,7 +1602,16 @@ acorn-jsx@^5.2.0:
|
|||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
|
||||
integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
|
||||
|
||||
acorn-walk@^7.1.1:
|
||||
acorn-node@^1.6.1:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
|
||||
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
|
||||
dependencies:
|
||||
acorn "^7.0.0"
|
||||
acorn-walk "^7.0.0"
|
||||
xtend "^4.0.2"
|
||||
|
||||
acorn-walk@^7.0.0, acorn-walk@^7.1.1:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||
|
@ -1604,10 +1621,10 @@ acorn@^6.4.1:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
|
||||
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
|
||||
|
||||
acorn@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
|
||||
integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
|
||||
acorn@^7.0.0, acorn@^7.1.1:
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
|
||||
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
|
||||
|
||||
aggregate-error@^3.0.0:
|
||||
version "3.0.1"
|
||||
|
@ -1913,18 +1930,18 @@ atob@^2.1.2:
|
|||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
autoprefixer@^9.6.1:
|
||||
version "9.7.4"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378"
|
||||
integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==
|
||||
autoprefixer@^9.4.5, autoprefixer@^9.6.1:
|
||||
version "9.8.6"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
|
||||
integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
|
||||
dependencies:
|
||||
browserslist "^4.8.3"
|
||||
caniuse-lite "^1.0.30001020"
|
||||
chalk "^2.4.2"
|
||||
browserslist "^4.12.0"
|
||||
caniuse-lite "^1.0.30001109"
|
||||
colorette "^1.2.1"
|
||||
normalize-range "^0.1.2"
|
||||
num2fraction "^1.2.2"
|
||||
postcss "^7.0.26"
|
||||
postcss-value-parser "^4.0.2"
|
||||
postcss "^7.0.32"
|
||||
postcss-value-parser "^4.1.0"
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
|
@ -2450,7 +2467,7 @@ bytes@3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
|
||||
|
||||
bytes@3.1.0:
|
||||
bytes@3.1.0, bytes@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
||||
|
@ -2543,6 +2560,11 @@ callsites@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
camelcase-css@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
|
||||
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
|
||||
|
||||
camelcase-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
|
||||
|
@ -2576,7 +2598,7 @@ caniuse-api@^3.0.0:
|
|||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001111:
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111:
|
||||
version "1.0.30001117"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz#69a9fae5d480eaa9589f7641a83842ad396d17c4"
|
||||
integrity sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==
|
||||
|
@ -2626,7 +2648,7 @@ chalk@^3.0.0:
|
|||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^4.0.0:
|
||||
"chalk@^3.0.0 || ^4.0.0", chalk@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
|
||||
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
|
||||
|
@ -2901,7 +2923,7 @@ color-string@^1.5.2:
|
|||
color-name "^1.0.0"
|
||||
simple-swizzle "^0.2.2"
|
||||
|
||||
color@^3.0.0:
|
||||
color@^3.0.0, color@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10"
|
||||
integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==
|
||||
|
@ -2909,6 +2931,11 @@ color@^3.0.0:
|
|||
color-convert "^1.9.1"
|
||||
color-string "^1.5.2"
|
||||
|
||||
colorette@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
|
||||
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||
|
||||
colors@^1.1.2:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
|
@ -2931,6 +2958,11 @@ commander@^2.11.0, commander@^2.19.0, commander@^2.20.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
|
||||
common-tags@1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
|
||||
|
@ -3304,6 +3336,11 @@ css-tree@1.0.0-alpha.37:
|
|||
mdn-data "2.0.4"
|
||||
source-map "^0.6.1"
|
||||
|
||||
css-unit-converter@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
|
||||
integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
|
||||
|
||||
css-what@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1"
|
||||
|
@ -3624,6 +3661,11 @@ define-property@^2.0.2:
|
|||
is-descriptor "^1.0.2"
|
||||
isobject "^3.0.1"
|
||||
|
||||
defined@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
|
||||
|
||||
del@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
|
||||
|
@ -3685,6 +3727,15 @@ detect-node@^2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||
|
||||
detective@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b"
|
||||
integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==
|
||||
dependencies:
|
||||
acorn-node "^1.6.1"
|
||||
defined "^1.0.0"
|
||||
minimist "^1.1.1"
|
||||
|
||||
diff-sequences@^24.9.0:
|
||||
version "24.9.0"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
|
@ -4763,7 +4814,7 @@ from2@^2.1.0:
|
|||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
fs-extra@8.1.0:
|
||||
fs-extra@8.1.0, fs-extra@^8.0.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
|
||||
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
|
||||
|
@ -5210,6 +5261,11 @@ html-escaper@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
|
||||
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
|
||||
|
||||
html-tags@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
|
||||
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
|
||||
|
||||
htmlparser2@^3.10.1:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
|
||||
|
@ -6808,6 +6864,11 @@ lodash.throttle@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash.toarray@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
||||
integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
|
||||
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
@ -6818,7 +6879,7 @@ lodash@4.17.15:
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.12:
|
||||
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.12:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
|
@ -7290,6 +7351,13 @@ node-cache@^4.1.1:
|
|||
clone "2.x"
|
||||
lodash "^4.17.15"
|
||||
|
||||
node-emoji@^1.8.1:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da"
|
||||
integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==
|
||||
dependencies:
|
||||
lodash.toarray "^4.4.0"
|
||||
|
||||
node-forge@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
|
||||
|
@ -7449,6 +7517,11 @@ normalize-url@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
||||
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
||||
|
||||
normalize.css@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3"
|
||||
integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==
|
||||
|
||||
npm-run-path@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
|
||||
|
@ -7514,6 +7587,11 @@ object-copy@^0.1.0:
|
|||
define-property "^0.2.5"
|
||||
kind-of "^3.0.3"
|
||||
|
||||
object-hash@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea"
|
||||
integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==
|
||||
|
||||
object-inspect@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||
|
@ -8228,6 +8306,16 @@ postcss-font-variant@^4.0.0:
|
|||
dependencies:
|
||||
postcss "^7.0.2"
|
||||
|
||||
postcss-functions@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e"
|
||||
integrity sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4=
|
||||
dependencies:
|
||||
glob "^7.1.2"
|
||||
object-assign "^4.1.1"
|
||||
postcss "^6.0.9"
|
||||
postcss-value-parser "^3.3.0"
|
||||
|
||||
postcss-gap-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715"
|
||||
|
@ -8261,6 +8349,14 @@ postcss-initial@^3.0.0:
|
|||
lodash.template "^4.5.0"
|
||||
postcss "^7.0.2"
|
||||
|
||||
postcss-js@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.3.tgz#a96f0f23ff3d08cec7dc5b11bf11c5f8077cdab9"
|
||||
integrity sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w==
|
||||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
postcss "^7.0.18"
|
||||
|
||||
postcss-lab-function@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e"
|
||||
|
@ -8397,6 +8493,14 @@ postcss-modules-values@^3.0.0:
|
|||
icss-utils "^4.0.0"
|
||||
postcss "^7.0.6"
|
||||
|
||||
postcss-nested@^4.1.1:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-4.2.3.tgz#c6f255b0a720549776d220d00c4b70cd244136f6"
|
||||
integrity sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw==
|
||||
dependencies:
|
||||
postcss "^7.0.32"
|
||||
postcss-selector-parser "^6.0.2"
|
||||
|
||||
postcss-nesting@^7.0.0:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052"
|
||||
|
@ -8663,7 +8767,7 @@ postcss-unique-selectors@^4.0.1:
|
|||
postcss "^7.0.0"
|
||||
uniqs "^2.0.0"
|
||||
|
||||
postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3:
|
||||
postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
|
||||
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
|
||||
|
@ -8682,7 +8786,7 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
|
|||
indexes-of "^1.0.1"
|
||||
uniq "^1.0.1"
|
||||
|
||||
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
|
||||
postcss@7.0.32, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
|
||||
version "7.0.32"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
|
||||
integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
|
||||
|
@ -8691,6 +8795,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.1
|
|||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^6.0.9:
|
||||
version "6.0.23"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
|
||||
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
|
||||
dependencies:
|
||||
chalk "^2.4.1"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^5.4.0"
|
||||
|
||||
prelude-ls@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
|
@ -8738,6 +8851,11 @@ pretty-format@^26.4.2:
|
|||
ansi-styles "^4.0.0"
|
||||
react-is "^16.12.0"
|
||||
|
||||
pretty-hrtime@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
||||
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
|
||||
|
||||
pretty@2.0.0, pretty@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5"
|
||||
|
@ -8860,6 +8978,16 @@ punycode@^2.1.0, punycode@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
purgecss@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-2.3.0.tgz#5327587abf5795e6541517af8b190a6fb5488bb3"
|
||||
integrity sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ==
|
||||
dependencies:
|
||||
commander "^5.0.0"
|
||||
glob "^7.0.0"
|
||||
postcss "7.0.32"
|
||||
postcss-selector-parser "^6.0.2"
|
||||
|
||||
q@^1.1.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
@ -9066,6 +9194,14 @@ redent@^2.0.0:
|
|||
indent-string "^3.0.0"
|
||||
strip-indent "^2.0.0"
|
||||
|
||||
reduce-css-calc@^2.1.6:
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.7.tgz#1ace2e02c286d78abcd01fd92bfe8097ab0602c2"
|
||||
integrity sha512-fDnlZ+AybAS3C7Q9xDq5y8A2z+lT63zLbynew/lur/IR24OQF5x98tfNwf79mzEdfywZ0a2wpM860FhFfMxZlA==
|
||||
dependencies:
|
||||
css-unit-converter "^1.1.1"
|
||||
postcss-value-parser "^3.3.0"
|
||||
|
||||
regenerate-unicode-properties@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
|
||||
|
@ -9269,7 +9405,7 @@ resolve-url@^0.2.1:
|
|||
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
||||
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
|
||||
|
||||
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1:
|
||||
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1:
|
||||
version "1.17.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
|
||||
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
|
||||
|
@ -10158,7 +10294,7 @@ supports-color@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
|
||||
|
||||
supports-color@^5.3.0:
|
||||
supports-color@^5.3.0, supports-color@^5.4.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
|
@ -10226,6 +10362,34 @@ table@^5.2.3:
|
|||
slice-ansi "^2.1.0"
|
||||
string-width "^3.0.0"
|
||||
|
||||
tailwindcss@^1.8.3:
|
||||
version "1.8.4"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-1.8.4.tgz#867a831640b0edf26517a691f6b6f5bd09aa3adf"
|
||||
integrity sha512-UW1giHUBuMVUwzff0vVbvGOdx1r8+4onN8LCblzncstdFVyuiZ2wCnkv2RQiSAlMTHaNu8vAAhm/fw3flmCi0Q==
|
||||
dependencies:
|
||||
"@fullhuman/postcss-purgecss" "^2.1.2"
|
||||
autoprefixer "^9.4.5"
|
||||
browserslist "^4.12.0"
|
||||
bytes "^3.0.0"
|
||||
chalk "^3.0.0 || ^4.0.0"
|
||||
color "^3.1.2"
|
||||
detective "^5.2.0"
|
||||
fs-extra "^8.0.0"
|
||||
html-tags "^3.1.0"
|
||||
lodash "^4.17.20"
|
||||
node-emoji "^1.8.1"
|
||||
normalize.css "^8.0.1"
|
||||
object-hash "^2.0.3"
|
||||
postcss "^7.0.11"
|
||||
postcss-functions "^3.0.0"
|
||||
postcss-js "^2.0.0"
|
||||
postcss-nested "^4.1.1"
|
||||
postcss-selector-parser "^6.0.0"
|
||||
postcss-value-parser "^4.1.0"
|
||||
pretty-hrtime "^1.0.3"
|
||||
reduce-css-calc "^2.1.6"
|
||||
resolve "^1.14.2"
|
||||
|
||||
tapable@^0.1.8:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
|
||||
|
@ -11281,7 +11445,7 @@ xmlchars@^2.2.0:
|
|||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
||||
|
||||
xtend@^4.0.0, xtend@~4.0.1:
|
||||
xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
|
Loading…
Reference in a new issue