1.0.2 • Published 12 months ago

miya-chat v1.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
12 months ago

miya-chat-library

NPM JavaScript Style Guide

Install

npm install --save miya-chat-library

TECHENGINESSRL

Usage 1

import MiYaChat from 'miya-chat-library'
import React from 'react'
import ReactDOM from 'react-dom'
import 'miya-chat-library/dist/index.css'

const div = document.createElement('div')
div.id = 'miya-chat-div'
document.body.appendChild(div)
ReactDOM.render(<MiYaChat text='123123123' />, div)

Usage 2

备注

#chat-component css style id选择器为整个chat的主题颜色

--floating-button-color: #ff550a !important

floating-button 和 notification 背景颜色

.single-select-input-button

.multi-select-input-button

.page-link-submit-button

.page-link-cancel-button

window.chat

  window.chat = {
    appId: "4efb89122",//每个应用(客户)的ID,由平台派发,固定值
    fingerprint: "",//浏览器指纹,可写入自定义 session id用于标记的访问用户
    // topic: "massima-energia/public",//chat对话主题,由平台派发,固定值
    topic: "massima-energia/clients",
    // topic: "demo",
    titleText: "Massimo",//chat对话框标题
    titleLogo: "./images/logo_massima_bianco.png",//chat对话框标题左边图标
    chatLogo: "./images/logo_massima_verde.png",//chat对话框消息部分bot头像
    chatLogoAnimation: "./images/logo_massima_verde.png",//chat对话框消息部分bot动画头像,动画只支持svg文件
    toolTipTitleText: "Ciao, sono Massimo.",//floating button tooltips text 标题
    toolTipMessageText: "L'assistente virtuale di Massima Energia.",//floating button tooltips text 内容
    defaultOpenChat: false,//表示默认chat对话框是否打开,为false时,页面打开显示floating button
    onLoaded: function() {
      // session id init

      // Initialize the agent at application startup.
      // You can also use https://openfpcdn.io/fingerprintjs/v3/esm.min.js
      const fpPromise = import("https://openfpcdn.io/fingerprintjs/v3").then(FingerprintJS => FingerprintJS.load());
      fpPromise.then(fp => fp.get()).then(result => {
        window.chat.fingerprint = result["visitorId"];
        window.chat.init();
      });
      //onLoaded为chat组件加载完成时主动调用,可以在这里初始化fingerprint的值,和其它一些初始化的动作。再需要显示chat的时修调用init()函数即可。
      //window.chat.init();必须在onLoaded中或onLoaded执行完成后调用.
    }
  };
<style type="text/css">
  #chat-component {
    --primary-color: #075C49 !important;
    --primary-color-50: #075C4980 !important;
    --primary-color-60: #075C4999 !important;
    --floating-button-color: #ff550a !important;
  }

  .single-select-input-button {
    background: #ff550a !important;
    border-radius: 20px !important;
  }

  .multi-select-input-button {
    background: #ff550a !important;
    border-radius: 20px !important;
  }

  .page-link-submit-button {
    background: #ff550a !important;
    border-radius: 20px !important;
  }

  .page-link-cancel-button {
    border-radius: 20px !important;
  }
</style>
<script type="text/javascript">
  window.chat = {
    appId: "4efb89122",
    fingerprint: "",
    // topic: "massima-energia/public",
    topic: "massima-energia/clients",
    // topic: "demo",
    titleText: "Massimo",
    titleLogo: "./images/logo_massima_bianco.png",
    chatLogo: "./images/logo_massima_verde.png",
    chatLogoAnimation: "./images/logo_massima_verde.png",
    toolTipTitleText: "Ciao, sono Massimo.",
    toolTipMessageText: "L'assistente virtuale di Massima Energia.",
    defaultOpenChat: false,
    onLoaded: function() {
      // session id init

      // Initialize the agent at application startup.
      // You can also use https://openfpcdn.io/fingerprintjs/v3/esm.min.js
      const fpPromise = import("https://openfpcdn.io/fingerprintjs/v3").then(FingerprintJS => FingerprintJS.load());
      fpPromise.then(fp => fp.get()).then(result => {
        window.chat.fingerprint = result["visitorId"];
        window.chat.init();
      });
    }
  };
</script>
<script defer="defer" src="./static/js/main.c74e21ed_v1.js"></script>
<link href="./static/css/main.3edc8478_v1.css" rel="stylesheet">

rewind按钮说明

如果中间的一个Message没有rewind操作,前面所有rewind操作将在此处截断

用户连续输入说明

只需要message中 title 字段为空即可

用户重新输入说明,比如API验证密码输入错误,需要重新输入

只需要date中 error字段写入重新输入的错误信息即可

IntegerNumberInput 整数的输入,可以输入负数

{
  id: 'demo-01',
  title: 'How much is your payment monthly (roughly)?',
  input: 'integer-number',
  attributes: {
    placeholder: 'Please enter number',
    maximum: 100,
    minimum: -20,
    defaultValue: '10',
    errors: {
      maximumError: 'the maximum value is 100',
      minimumError: 'the minimum value is -20'
    }
  },
  additional: [
    'feedback',
    'rewind'
  ],
  var_name: 'monthly',
  value_type: 'integer'
}

FloatNumberInput 带小数浮点的输入,可以输入负数

小数点的长度取maximum或minimum的最大值,如果maximum或minimum都写的整数,则默认取2位长度
{
  id: '0-1-10-1',
  title: '',
  input: 'float-number',
  attributes: {
    placeholder: 'Please enter float number',
    maximum: 100.99,
    minimum: -20.20,
    defaultValue: '10.56',
    errors: {
      maximumError: 'the maximum value is 100.99',
      minimumError: 'the minimum value is -20.20'
    }
  },
  additional: [
    'feedback',
    'rewind'
  ],
  var_name: 'mthinsurance',
  value_type: 'integer'
}

GeneralTextInput 一般文本输入,只有长度限制

{
  id: '0-1-10-222',
  title: '',
  input: 'general-text',
  attributes: {
    placeholder: 'Please enter text',
    maxLength: 20,
    minLength: 1,
    defaultValue: 'hello world',
    errors: {
      maxLengthError: 'the maximum length is 20',
      minLengthError: 'the minimum length is 1',
    },
  },
  additional: ['feedback', 'rewind'],
  var_name: 'name',
  value_type: 'string',
}

PasswordTextInput 密码输入

{
  id: '0-1-10-223',
  title: '',
  input: 'password-text',
  attributes: {
    placeholder: 'Please enter password',
    maxLength: 20,
    minLength: 6,
    defaultValue: '',
    errors: {
      maxLengthError: 'the maximum length is 20',
      minLengthError: 'the minimum length is 6',
    },
  },
  additional: ['feedback', 'rewind'],
  var_name: 'password',
  value_type: 'string',
}

PhoneTextInput 手机号输入 formatMatcher为正则,需要根据不同国家的手机号写匹配正则

formatMatcher为空提交时不验证文本格式,只验证长度。固定长度maxLength和minLength相同即可
{
  id: '0-1-10-223',
  title: '',
  input: 'phone-text',
  attributes: {
    placeholder: 'Please enter phone',
    maxLength: 13,
    minLength: 8,
    defaultValue: '',
    formatMatcher: '^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$',
    errors: {
      maxLengthError: 'the maximum length is 13',
      minLengthError: 'the minimum length is 8',
      formatError: 'the phone format error'
    }
  },
  additional: [
    'feedback',
    'rewind'
  ],
  var_name: 'password',
  value_type: 'string'
}

EmailTextInput email输入 email的输入不区分大小写,统一转小写验证

{
  id: '0-1-10-223',
  title: '',
  input: 'email-text',
  attributes: {
    placeholder: 'Please enter email',
    maxLength: 56,
    defaultValue: '',
    formatMatcher: '^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[\.][a-z]{2,3}([\.][a-z]{2})?$',
    errors: {
      formatError: 'the email format error'
    }
  },
  additional: [
    'feedback',
    'rewind'
  ],
  var_name: 'email',
  value_type: 'string'
}

DateTextInput date输入,验证格式由正则确定

http://momentjs.cn/docs/#/manipulating/add/
today表示今天日期 +d30  今天日期加30天
today表示今天日期 -d30  今天日期减30天
{
  id: '0-1-10-223',
  title: '',
  input: 'date-text',
  attributes: {
    placeholder: 'GG/MM/YYYY',
    maxDate: '31/12/2025',
    minDate: 'today',
    //minDate: '01/01/2012',
    defaultValue: '',
    formatMatcher: 'DD/MM/YYYY',
    errors: {
      formatError: 'the date format error',
      maxDateError: 'the maximum date is {maxDate}',
      minDateError: 'the minimum date is {minDate}',
    },
  additional: [
    'feedback',
    'rewind'
  ],
  var_name: 'date',
  value_type: 'string'
}

SelectInput 列表单选择输入

{
  id: '0-1-10-2',
  title: '',
  input: 'list-select',
  list: [{ key: 'Yes', value: 'Y' }, { key: 'No', value: 'N' }],
  additional: ['feedback'],
  var_name: 'select',
  value_type: 'string'
}

MultiSelectInput 列表多选择输入

{
  id: '0-1-10-2',
  title: '',
  input: 'multi-select',
  list: [
    { key: 'Sposato(a)', value: 'M' },
    { key: 'Single', value: 'S' },
    { key: 'Convivente', value: 'C' },
    { key: 'Separato(a) / Divorziato(a)', value: 'D' },
    { key: 'Vedovo(a)', value: 'W' }
  ],
  additional: ['feedback', 'rewind'],
  var_name: 'select',
  value_type: 'string'
}

SingleSelectInput 列表单选择输入

{
  id: '0-1-10-2',
  title: '',
  input: 'single-select',
  attributes: {
    select: {
      key: `<div>Confermo la presa visione dell'<a href="#">Informativa sulla Privacy</a> (Informativa ai sensi degli
    articoli 13 e 14 del Regolamento Europeo 2016/679 e della normativa italiana di armonizzazione)<br/>
    Inserimento di dati di contatto:</div>`,
      value: 'confermo',
    },
  },
  additional: ['feedback', 'rewind'],
  var_name: 'single-select',
  value_type: 'string'
}

FuzzySearchTextInput 搜索输入,有一个字段defaultList用于存放热门搜索结果集,组件加载时就显示了,用户可以直接选择输入

搜索接口对应POST /fuzzy-search
const { search: { keyword, referenceId } } = req.body
referenceId为当前bot message的id
{
  id: 'demo-01',
  title: 'Come ti chiami (può essere un soprannome)?',
  attributes: {
    placeholder: 'Inserisci 2 lettere e seleziona',
    maxLength: 13,
    minLength: 2,
    errors: {
      maxLengthError: 'the maximum length is 20',
      minLengthError: 'the minimum length is 1',
    },
    defaultList: [
      { key: 'Aiuto giardiniere', value: '21' },
      { key: 'Allenatore cavalli', value: '22' },
      { key: 'Allenatore di cani', value: '23' },
      { key: 'Allenatore professionale', value: '24' },
      { key: 'Allenatore sportivo', value: '25' },
      { key: 'Allennatore non professionale', value: '26' },
      { key: 'Allevatore', value: '27' },
    ],
  },
  input: 'fuzzy-search-text',
  additional: ['feedback', 'rewind'],
  var_name: 'search',
  value_type: 'string'
}

SelectDateTimeInput 时间选择输入

days向后可选天数,skipWeek是否跳过周未,times定义当天可选的工作时间段,没有的取默认值
times要过滤当天已经过时间段,需要再后端API中过滤,组件只做显示,times的日期为空数组时会被忽略
组件暂时不支持取实时的 times
holidays为排除指定日期的时间,当holidays的日期为空时,表示禁用当天日期的选择,不空为时只禁用时间
{
  id: 'demo-01', title: 'Choose a meeting time.', input: 'datetime-select', attributes: {
    selectable: {
      days: 30, skipWeek: true, times: {
        '2022-03-08': ['08:30', '09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '14:00', '14:30', '15:00'], '2022-03-09': ['09:30', '10:00', '10:30', '11:00'],
      },
      holidays: [{ '2022-04-18': ['09:30', '10:00', '10:30', '14:00'] }]
    }, defaultWorkHours: [
      '08:00', '08:30', '09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00', '17:30', '18:00', '18:30'],
  }, additional: ['feedback', 'rewind'],
}

Upload 文件或图片上传输入

{
          id: 'demo-01',
          title: 'Choose a  uploads file.',
          input: 'upload',
          attributes: {
            accept: 'accept=image/*',
            imgExtension: ['.jpg', '.gif', '.png'],
            maxFileSize: 5242880,
            fileSizeError: ' file size is too big',
            fileTypeError: ' is not supported file extension',
            singleImage: false,
          },
          additional: ['feedback', 'rewind'],
}

Result 结果返回

result中的title不支持数组,results本身是一个数据,要实现多次输出,只需要在result中加入 {title:"",type:"text"} 即可
*建议title不显示时也写一个不空为的title,可以是下面按钮的描述,方便阅读理解

result中的type button有两个值 为button1和button2

区别 button1中,buttons中每项有一个title值单独显示在button上面,results中的titles不显示
    button2中,buttons中每项没有title,results中的title显示在最上面。

tooltips为链接跳转时的重定向提示文字,默认为空

当display为false时,所有的title不显示

link有字符串值"message","tel:213123123"
     Object值 {url:"http://www.google.com",visible:"false"}
     visible为url是否在跳转提示页面中显示。默认是true.
{
    id: '2-3-2-2',
    input: 'result',
    display:false
    results: [
      {
        title: 'Visualizza la guida alla lettura:',
        type: 'button1',
        buttons: [
          {
            title: 'Vai alla guida', text: 'Vai alla guida', style: { background: '#ff550a', borderRadius: 20, color: '#fff' },
            link: { url: `https://www.massimaenergia.it/bolletta-2-0`, visible: false },
            tooltips: 'Stai per essere reindirizzato alla guida alla lettura della bolletta',
          },
          {
            title: 'Riavvia la chat', text: 'Riavvia la chat', style: { background: 'aliceblue', borderRadius: 20, color: 'rgb(0 0 0)' },
            link: `message`,
          },
        ],
      },
    ],
    additional: ['feedback', 'rewind'],
}

Message 结果返回

当input为Message时间,显示一个独立的bot消息,同时会接着自动请求下一个消息,撤回时,为message question的上一个index
  {
    id: '1-1-3',
    title: [
      `<div><strong>COSA E'</strong><br> </div>`,
      `<div> <strong>MODALITA'</strong><br/></div>`],
    input: 'message',
  },

特殊字段说明

{
  id: '1',
  title: 'Consenso trattativa dati personali',
  input: 'single-select',
  display: false,
  attributes: {
    select: {
      key: `<div>Confermo la presa visione dell'<a href="#" target="_blank">Informativa sulla Privacy</a> (Informativa ai sensi degli
    articoli 13 e 14 del Regolamento Europeo 2016/679 e della normativa italiana di armonizzazione)<br/>
    Inserimento di dati di contatto:</div>`,
      value: 'confermo',
    },
    record: 'none',
  },
  additional: ['feedback', 'rewind'],
}
1. display:false  表示bot边上的message不显示,不写默认为true
   当title为空时 bot边上的message也不显示,使用display为保留title在数据记录中
   根据使用场景决定使用
2. record: 'none' 表示当 action input 输入提交后,bot边上的message和user边上的message不在界面上显示,不写默认为block

命令执行

参数字段放在  attributes>command中
cond为条件字段,目前只做了value的对比。
func为函数名
arg为函数参数

command的目前为同步等待执行,异步状态待开发...
{
  id: '2',
  title: 'Possiamo esserti d\'aiuto con altro? ',
  input: 'list-select',
  list: [
    { key: 'Sì', value: 'si' },
    { key: 'No, grazie', value: 'no' },
  ],
  attributes: {
    command: { cond: 'no', func: 'doClose', arg: [] },
  },
  additional: ['feedback', 'rewind'],
  var_name: 'LIST_RESTART',
  value_type: 'text',
}

i18

react-i18next

chat初始化语言跟随window.chat.language变量变化而变化,默认值为en

  window.chat.language = "en" | "zh" | "ita"
  • How to use
// use hook
export function MyComponent() {
  const { t, i18n } = useTranslation();
  // or const [t, i18n] = useTranslation();

  return (
  <p>{t('my translated text')}</p>
  // or <Component label={t('my translated text')} />
  )
}

// use HOC

import { withTranslation } from 'react-i18next';

function MyComponent({ t, i18n }) {
  return <p>{t('my translated text')}</p>
}

export default withTranslation()(MyComponent);

// render prop
import { Translation } from 'react-i18next';

export function MyComponent() {
  return (
    <Translation>
      {
        (t, { i18n }) => <p>{t('my translated text')}</p>
      }
    </Translation>
  )
}
  • How to add new language
  // add new json file in src/locales/xx/translation.json
  // add new language in src/locales/i18n.js
  const resources = {
    ...
    newLanguage: {
      translation: require('./xx/translation.json')
    }
  }

 // or
  import translationNewLang from './xx/translation.json'
  const resources = {
    ...
    newLanguage: {
      translation: translationNewLang
      }
  }
  • Suppoer multiple Translation Files
  // add new json file in src/locales/xx/xxx.json
  // add new file in src/locales/i18n.js
  const resources = {
    ...
    newLanguage: {
      translation: require('./xx/translation.json'),
      xxx: require('./xx/xxx.json')
    }
  }

  // use
  const { t } = useTranslation(['translation', 'xxx']);

For more usage, see multiple Translation Files

  • todo 由于当前只语言是通过window.chat.language变量来控制的,所以在切换语言时,需要手动刷新页面。 后续若需自动刷新页面,可在chat组件中监听window.chat.language变量的变化,然后调用i18n.changeLanguage方法。