كيف أصبحت Smartcalls Kit Voximplant Kit - ميزات تغيير العلامة التجارية والقاتلة


لفترة طويلة كنا نستعد لتحديث Smartcalls ، محرر بصري للمكالمات الصادرة ، والآن حدث ذلك. اليوم ، تحت التخفيض ، سنتحدث عن تغييرات UI / UX ونتسلق تحت غطاء الوضع التجريبي لإظهار كيف قمنا بترويض JointJS .

ما الذي تغير بالفعل؟


من الأكثر وضوحًا - اسم وعنوان URL جديد ، مما يعني أن مجموعة Voximplant Kit متاحة على الرابط المناسب voximplant.com/kit . قمنا أيضًا بتعديل صفحة التسجيل ، وهي الآن كما يلي:

صورة

على الرغم من أن المفهوم ظل كما هو ، إلا أن واجهة المنتج تغيرت بشكل كبير ، لتصبح أكثر سهولة في الاستخدام. انتقلت القائمة العلوية إلى اليسار ، مما جعل التنقل بين الكتل أكثر منطقية وملاءمة.

صورة

بالإضافة إلى ذلك ، يتوفر الآن تجميع وفرز النصوص والتسجيلات الصوتية ، والبحث بالأرقام ، بالإضافة إلى بطاقات الحملة التي تحتوي على معلومات موجزة عنها ، بما في ذلك المؤشرات الجديدة - متوسط ​​مدة المكالمة الناجحة وإجمالي المبلغ المنفق.

صورة

بالنسبة للتكامل: وصلت الواجهة سهلة الاستخدام إلى إعدادات البريد ، وعلى علامات التبويب Dialogflow و SIP و Global Variables ، ظهر بحث وفرز الملفات حسب المعرّف والمضيف.

صورة

بشكل عام ، الكثير من الجديد والرائع! اقرأ المزيد حول التغييرات في مدونتنا .

لكن أهم شيء هو المحرر


الوضع التجريبي (المفسد: هذه هي ميزة القاتل الرئيسية).


تنفيذ برنامج نصي في الوقت الفعلي مع تمييز الكتل المشاركة ، وبعد التنفيذ - نتيجة مكالمة (Flow and Log) ، مما يجعل تصحيح البرامج النصية أسهل وأسرع.

صورة

يمكنك مشاهدة فيديو الوضع التجريبي هنا أو اختباره بنفسك بعد التسجيل في Voximplant Kit .

وكيف يتم تنفيذ كل هذا ، سنخبرنا في القسم التالي. الميزات الجديدة للمحرر:

  • تراجع / إعادة (1 في الصورة أدناه) ؛
  • مفاتيح التشغيل السريع (2) ؛
  • قائمة منبثقة حيث يمكنك محاذاة الكتل والروابط بينها بنقرة واحدة ، وتغيير المقياس ، والعمل مع miniMap ، وتوسيع البرنامج النصي إلى ملء الشاشة ، ومشاركته أيضًا (نسخ أو حفظ كملف png) (3) ؛
  • انقر بزر الماوس الأيمن على قائمة السياق ؛
  • نسخ الكتل - ليس فقط داخل نفس البرنامج النصي ، ولكن أيضًا بين النصوص المختلفة وحتى (!) الحسابات المختلفة ؛
  • قفل / فتح كتلة - يمكن نقل كتلة مقفلة ، ولكن لا يمكن تحريرها لتجنب التغييرات غير المرغوب فيها ؛
  • تغيير اللون - بصريًا يمكنك تحديد العديد من الكتل "ذات الصلة" ؛
  • البحث عن طريق أسماء ومحتويات الكتل المستخدمة ؛
  • كتلة "القائمة التفاعلية" - القدرة على تبديل المنافذ (خيارات الإجابة) في الأماكن ببساطة عن طريق السحب والإسقاط.

صورة

نكشف البطاقات


حان الوقت لمعرفة كيفية تنفيذ الرسوم المتحركة في الكود.


يستدعي المحرر طريقة HTTP API الخاصة بنا - StartScenarios - لتشغيل البرنامج النصي السحابي. تبدأ سحابة Voximplant النص البرمجي وتعطيه لمحرر media_access_url. من هذه اللحظة ، يسحب المحرر media_access_url كل ثانية ، ويتلقى معلومات حول كيفية "انتقال" النص البرمجي عبر الكتل في الاستجابة - استنادًا إلى هذه البيانات ، يبرز المحرر الكتل الضرورية ويحيي الاتصالات بينها.

History هو كائن JSON يحتوي على الحقول التالية:

  • الطابع الزمني
  • idSource - الكتلة الأولية ؛
  • idTarget - الكتلة النهائية ؛
  • المنفذ - المنفذ (قد يكون هناك العديد من المخرجات من كتلة واحدة).

صورة

بمساعدة هذه المتغيرات المخصصة والخدمية ، تدرك الواجهة الأمامية الكتلة التي تمر بها أثناء الاختبار. كيف يفهم هذا؟ عندما يحدث البناء المرئي (تتم إضافة كتلة جديدة) ، يتم تعيين معرف على الفور ، والذي يتم استخدامه بعد ذلك في السجل كمعرف المصدر / معرف الهدف.

لتنفيذ هذه الوظيفة ، استخدمنا مكتبة JointJS ، ولكن كان هناك بعض التعليمات البرمجية المكتوبة ذاتيًا.

لنبدأ بالطريقة الرئيسية selectBlock () ، وهي تعمل على النحو التالي: ننتقل عبر مصفوفة محفوظات الحركة (idSource ، idTarget) وبمجرد أن نجد نقاط البداية والنهاية ، ابحث عن الاتصال بينهما:

const link = this.editor.getTestLink(sourceCell, portId);

إذا كان هناك اتصال بينهما ، فإننا نحرك كرة تعمل على طول خط الاتصال:
if (link) this.setLinkAnimation(link);

يتم استدعاء طريقة selectBlock () بعد كل تحديث لهذا التاريخ. نظرًا لأن العديد من الكتل التي تم تمريرها يمكن أن تصل إلى this.testHistory في وقت واحد ، فإننا نسمي بشكل متكرر selectBlock مرة واحدة كل 700 مللي ثانية (هذا هو الوقت التقريبي الذي يقضيه في تحريك الحركة من كتلة إلى أخرى):

setTimeout(this.selectBlock, 700);

جميع التعليمات البرمجية لهذه الطريقة هي كما يلي. انتبه إلى طرق selectTestBlock و getTestLink ، السطران 7 و 10 - الآن سنتحدث عنها بشكل منفصل:

selectBlock ( ) : باطل {
if ( this . historyIndex < this . testHistory . length ) {
const i = this . historyIndex .
const targetCellId = this.testHistory[i].idTarget;
const sourceCellId = this.testHistory[i].idSource;
const portId = this.testHistory[i].port;
const targetCell = this.editor.selectTestBlock(targetCellId);
const sourceCell = this.editor.getCell(sourceCellId);
if (sourceCell && targetCell) {
const link = this.editor.getTestLink(sourceCell, portId);
if (link) this.setLinkAnimation(link);
}
this.historyIndex += 1;
setTimeout ( this . selectBlock ، 700 ) ؛
}}
}}
عرض الخام selectBlock.js مستضاف بواسطة it بواسطة GitHub


ارسم اتصالًا


تساعد طريقة getTestLink () في الحصول على الاتصال بين الكتل - وهي تعتمد على getConnectedLinks () ، وهي طريقة JointJS مضمنة تأخذ مدخل كتلة وتعرض صفيفًا من الروابط. في تطبيقنا ، نحن نبحث في الصفيف الناتج عن ارتباط بمنفذ ، حيث تحتوي الخاصية المصدر على قيمة portId:

link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item => {
     return item.get('source').port === portId;

ثم ، إذا كان هناك رابط ، فقم بتمييزه:

return link ? (link.toFront() && link) : null;

كود الطريقة:

getTestLink(sourceCell: Cell, portId: string): Link {
  let link = null;
  if (sourceCell && sourceCell.id) {
    let cell = null;
    if (sourceCell.type === 'ScenarioStart' || sourceCell.type === 'IncomingStart') {
      cell = this.getStartCell()
    } else {
      cell = this.graph.getCell(sourceCell.id);
    }
    link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item => {
      return item.get('source').port === portId;
    });
  }
  return link ? (link.toFront() && link) : null;
}
 

يتم تنفيذ الرسوم المتحركة للكرة الجارية بالكامل عن طريق JointJS ( انظر العرض ).

ننتقل إلى الكتلة الحالية


نسمي طريقة selectTestBlock () عندما يكون من الضروري تحديد الكتلة النهائية ونقل اللوحة القماشية إليها. هنا نحصل على إحداثيات مركز الكتلة:

const center = cell.getBBox().center();

ثم استدعاء setTestCell () لتلوين الكتلة:

editor.tester.setTestCell(cell);

أخيرًا ، قمنا بالتكبير إلى مركزه باستخدام وظيفة zoomToCell () المكتوبة ذاتيًا (وهي الأكثر إثارة للاهتمام ، ولكنها في النهاية):

editor.paperController.zoomToCell(center, 1, false);

كود الطريقة:

selectTestBlock(id: string): Cell {
 const cell = (id === 'ScenarioStart') ? editor.tester.getStartCell() : editor.graph.getCell(id);
 if (cell) {
   const center = cell.getBBox().center();
   editor.tester.setTestCell(cell);
   editor.paperController.zoomToCell(center, 1, false);
 }
 return cell;
}

طريقة التلوين: اعثر على عنصر SVG من مجموعتنا وأضف فئة CSS التي تم اختبارها لجعل لون الكتلة:

setTestCell(cell: Cell): void {
 const view = cell.findView(this.paper);
 if (view) view.el.classList.add('is-tested');
}

تكبير سلس


أخيرًا ، zoomToCell ()! يحتوي JointJS على طريقة مدمجة لتحريك اللوحة القماشية على محوري X و Y ، في البداية أرادوا أخذها. ومع ذلك ، تستخدم هذه الطريقة التحويل كسمة لعلامة SVG ؛ فهي لا تدعم الرسوم المتحركة السلسة في متصفح Firefox + وتستخدم وحدة المعالجة المركزية فقط.

لقد قمنا باختراق صغير - لقد كتبنا وظيفتنا zoomToCell () ، والتي ، في جوهرها ، تفعل نفس الشيء ، ولكن يلقي التحويل على أنها CSS مضمنة ، وهذا يسمح لنا بالتصوير باستخدام GPU (لأن WebGL متصل بالعملية). وبالتالي ، يتم حل مشكلة التوافق عبر المتصفح.

لا تعمل وظيفتنا على تحريك اللوحة القماشية في XY فحسب ، بل تسمح لنا أيضًا بالتكبير / التصغير في نفس الوقت من خلال استخدام مصفوفة التحويل.

تخبر خاصية will-change للفئة. animate-viewport المتصفح أنه سيتم تغيير العنصر ويجب تطبيق التحسينات ، بما في ذلك استخدام GPU ، وتضبط خاصية الانتقال سلاسة نقل اللوحة إلى الكتلة:

.animate-viewport {
 will-change: transform;
 transition: transform 0.5s ease-in-out;

كل رمز طريقتنا أدناه:

public zoomToCell(center: g.Point, zoom: number, offset: boolean = true): void {
   this.updateGridSize();
   const currentMatrix = this.paper.layers.getAttribute('transform');
   //   svg-,        center
   //   ,     style
   const { a, b, c, d, e, f } = this.zoomMatrix(zoom, center, offset);
   //  FireFox    ,       
   this.paper.layers.style.transform = currentMatrix;
   //    FF  ,     ,    
   setTimeout(() => {
     //  CSS- .animate-viewport,    - transition;
     //    style      - transition
     this.paper.layers.classList.add('animate-viewport');
     this.paper.layers.style.transform = `matrix(${ a }, ${ b }, ${ c }, ${ d }, ${ e }, ${ f })`;
     const duration = parseFloat(getComputedStyle(this.paper.layers)['transitionDuration']) * 1000;
     //        style;
     //      joint
     setTimeout(() => {
       this.paper.layers.classList.remove('animate-viewport');
       this.paper.layers.style.transform = null;
       this.paper.matrix(newMatrix);
       this.paper.trigger('paper:zoom');
       this.updateGridSize();
       this.paper.trigger('paper:update');
     }, duration);
   }, 100);
 }

كما اتضح ، في بعض الأحيان تحتاج حتى أكثرها تقدمًا إلى الانتهاء من ملف :) نأمل أن تكون قد استمتعت بالحفر داخل الحوت (بغض النظر عن مدى رعبه). نتمنى لكم تطوراً ناجحاً مع مجموعة Voximplant Kit والمزيد!

All Articles