WP Live Chat Support - Version 8.1.3

Version Description

  • 2019-10-31
  • Bugfix: Admin detected as an agent - doesn't show offline messages form
  • Bugfix: Remove picture from chat box doesn't work properly
  • Bugfix: Edge JS compatibility issue in dashboard has been fixed
  • Bugfix: The page will no longer refresh upon ending a chat with an agent.
  • New feature: Agent online/offline switch in Wordpress admin bar
  • New feature: Adjustable chatbox height 30% - 80% of page size
  • Improvement: Cleaned up async_storage functions
  • Improvement: Better alignment for chat popup with no picture
  • Improvement: Reworked agent online/offline functions
  • Improvement: Default business hours are now 9:00 - 18:00 instead of 00:00 - 00:00
  • Improvement: The 'Use Logged In User Details' feature has been moved to the 'Chat Box' settings page
Download this release

Release Info

Developer WP-LiveChat
Plugin Icon 128x128 WP Live Chat Support
Version 8.1.3
Comparing to
See all releases

Code changes from version 8.1.2 to 8.1.3

ajax/agent.php CHANGED
@@ -14,7 +14,7 @@
14
 
15
  function wplc_init_agent_ajax_callback() {
16
 
17
- if(wplc_ic_check_if_user_is_agent() === "not_user_agent") {
18
  $array['error'] = 1;
19
  echo json_encode($array);
20
  die();
14
 
15
  function wplc_init_agent_ajax_callback() {
16
 
17
+ if (!wplc_user_is_agent()) {
18
  $array['error'] = 1;
19
  echo json_encode($array);
20
  die();
changelog.txt CHANGED
@@ -1,3 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 8.1.2 - 2019-10-24
2
  * New feature: improved auto pop-up feature, now 3 options to choose from
3
  * New feature: Pop-up only when agents are online
1
+ = 8.1.3 - 2019-10-31
2
+ * Bugfix: Admin detected as an agent - doesn't show offline messages form
3
+ * Bugfix: Remove picture from chat box doesn't work properly
4
+ * Bugfix: Edge JS compatibility issue in dashboard has been fixed
5
+ * Bugfix: The page will no longer refresh upon ending a chat with an agent.
6
+ * New feature: Agent online/offline switch in Wordpress admin bar
7
+ * New feature: Adjustable chatbox height 30% - 80% of page size
8
+ * Improvement: Cleaned up async_storage functions
9
+ * Improvement: Better alignment for chat popup with no picture
10
+ * Improvement: Reworked agent online/offline functions
11
+ * Improvement: Default business hours are now 9:00 - 18:00 instead of 00:00 - 00:00
12
+ * Improvement: The 'Use Logged In User Details' feature has been moved to the 'Chat Box' settings page.
13
+
14
  = 8.1.2 - 2019-10-24
15
  * New feature: improved auto pop-up feature, now 3 options to choose from
16
  * New feature: Pop-up only when agents are online
config.php CHANGED
@@ -7,7 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
9
 
10
- define('WPLC_PLUGIN_VERSION', "8.1.2");
11
  define('WPLC_PLUGIN_DIR', dirname(__FILE__));
12
  define('WPLC_PLUGIN_URL', plugins_url( '/', __FILE__ ) );
13
  define('WPLC_PLUGIN', plugin_basename( __FILE__ ) );
7
  exit;
8
  }
9
 
10
+ define('WPLC_PLUGIN_VERSION', "8.1.3");
11
  define('WPLC_PLUGIN_DIR', dirname(__FILE__));
12
  define('WPLC_PLUGIN_URL', plugins_url( '/', __FILE__ ) );
13
  define('WPLC_PLUGIN', plugin_basename( __FILE__ ) );
css/bootstrap.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["../../scss/bootstrap.scss","bootstrap.css","../../scss/_root.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/_tables.scss","../../scss/mixins/_table-row.scss","../../scss/_functions.scss","../../scss/_forms.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_forms.scss","../../scss/mixins/_gradients.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/mixins/_nav-divider.scss","../../scss/_button-group.scss","../../scss/_input-group.scss","../../scss/_custom-forms.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/mixins/_badge.scss","../../scss/_jumbotron.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_media.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/utilities/_align.scss","../../scss/mixins/_background-variant.scss","../../scss/utilities/_background.scss","../../scss/utilities/_borders.scss","../../scss/utilities/_display.scss","../../scss/utilities/_embed.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_float.scss","../../scss/utilities/_overflow.scss","../../scss/utilities/_position.scss","../../scss/utilities/_screenreaders.scss","../../scss/mixins/_screen-reader.scss","../../scss/utilities/_shadows.scss","../../scss/utilities/_sizing.scss","../../scss/utilities/_stretched-link.scss","../../scss/utilities/_spacing.scss","../../scss/utilities/_text.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_text-emphasis.scss","../../scss/mixins/_text-hide.scss","../../scss/utilities/_visibility.scss","../../scss/_print.scss"],"names":[],"mappings":"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AF7G1B;;AAEA;EEmHE,wBAAwB;AFjH1B;;AEyHA;EACE,aAAa;EACb,0BAA0B;AFtH5B;;AE6HA;EACE,qBAAqB;AF1HvB;;AE6HA;EACE,kBAAkB;EAClB,eAAe;AF1HjB;;AE6HA;EACE,aAAa;AF1Hf;;AAEA;EE8HE,wBAAwB;AF5H1B;;AM/VA;;EAEE,qBHiSuC;EG/RvC,gBHiS+B;EGhS/B,gBHiS+B;AHgEjC;;AM7VA;EFgHM,iBAtCY;AJuRlB;;AMhWA;EF+GM,eAtCY;AJ2RlB;;AMnWA;EF8GM,kBAtCY;AJ+RlB;;AMtWA;EF6GM,iBAtCY;AJmSlB;;AMzWA;EF4GM,kBAtCY;AJuSlB;;AM5WA;EF2GM,eAtCY;AJ2SlB;;AM9WA;EFyGM,kBAtCY;EEjEhB,gBHmS+B;AH8EjC;;AM7WA;EFmGM,eAtCY;EE3DhB,gBHsR+B;EGrR/B,gBH6Q+B;AHmGjC;;AM9WA;EF8FM,iBAtCY;EEtDhB,gBHkR+B;EGjR/B,gBHwQ+B;AHyGjC;;AM/WA;EFyFM,iBAtCY;EEjDhB,gBH8Q+B;EG7Q/B,gBHmQ+B;AH+GjC;;AMhXA;EFoFM,iBAtCY;EE5ChB,gBH0Q+B;EGzQ/B,gBH8P+B;AHqHjC;;AE1VA;EIhBE,gBH0EW;EGzEX,mBHyEW;EGxEX,SAAS;EACT,wCHzCa;AHuZf;;AMtWA;;EFMI,cAAW;EEHb,gBHsN+B;AHmJjC;;AMtWA;;EAEE,cH8PgC;EG7PhC,yBHsQmC;AHmGrC;;AMjWA;EC/EE,eAAe;EACf,gBAAgB;APoblB;;AMjWA;ECpFE,eAAe;EACf,gBAAgB;APyblB;;AMnWA;EACE,qBAAqB;ANsWvB;;AMvWA;EAII,oBHgP+B;AHuHnC;;AM7VA;EFjCI,cAAW;EEmCb,yBAAyB;ANgW3B;;AM5VA;EACE,mBHiBW;ECFP,kBAtCY;AJuXlB;;AM5VA;EACE,cAAc;EF7CZ,cAAW;EE+Cb,cH1GgB;AHyclB;;AMlWA;EAMI,qBAAqB;ANgWzB;;AQndA;ECIE,eAAe;EAGf,YAAY;ATidd;;AQldA;EACE,gBL++BwC;EK9+BxC,sBLRa;EKSb,yBLNgB;EOLd,sBPqOgC;EM/NlC,eAAe;EAGf,YAA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AAwB,iBADZ;IACY,QADZ;EfitClB;EehtCM;IAAwB,iBADZ;IACY,QADZ;EfotClB;EentCM;IAAwB,iBADZ;IACY,QADZ;EfutClB;EettCM;IAAwB,iBADZ;IACY,QADZ;Ef0tClB;EeztCM;IAAwB,iBADZ;IACY,QADZ;Ef6tClB;Ee5tCM;IAAwB,iBADZ;IACY,QADZ;EfguClB;Ee/tCM;IAAwB,iBADZ;IACY,QADZ;EfmuClB;EeluCM;IAAwB,iBADZ;IACY,QADZ;EfsuClB;EeruCM;IAAwB,iBADZ;IACY,QADZ;EfyuClB;EexuCM;IAAwB,iBADZ;IACY,QADZ;Ef4uClB;Ee3uCM;IAAwB,kBADZ;IACY,SADZ;Ef+uClB;Ee9uCM;IAAwB,kBADZ;IACY,SADZ;EfkvClB;EejvCM;IAAwB,kBADZ;IACY,SADZ;EfqvClB;Ee9uCQ;IFTR,cAA4B;Eb0vC5B;EejvCQ;IFTR,sBAA8C;Eb6vC9C;EepvCQ;IFTR,uBAA8C;EbgwC9C;EevvCQ;IFTR,gBAA8C;EbmwC9C;Ee1vCQ;IFTR,uBAA8C;EbswC9C;Ee7vCQ;IFTR,uBAA8C;EbywC9C;EehwCQ;IFTR,gBAA8C;Eb4wC9C;EenwCQ;IFTR,uBAA8C;Eb+wC9C;EetwCQ;IFTR,uBAA8C;EbkxC9C;EezwCQ;IFTR,gBAA8C;EbqxC9C;Ee5wCQ;IFTR,uBAA8C;EbwxC9C;Ee/wCQ;IFTR,uBAA8C;Eb2xC9C;AACF;;AgBz0CA;EACE,WAAW;EACX,mBb2HW;Ea1HX,cbSgB;AHm0ClB;;AgB/0CA;;EAQI,gBb8UgC;Ea7UhC,mBAAmB;EACnB,6BbJc;AHg1ClB;;AgBt1CA;EAcI,sBAAsB;EACtB,gCbTc;AHq1ClB;;AgB31CA;EAmBI,6Bbbc;AHy1ClB;;AgBn0CA;;EAGI,ebwT+B;AH6gCnC;;AgB5zCA;EACE,yBbnCgB;AHk2ClB;;AgBh0CA;;EAKI,yBbvCc;AHu2ClB;;AgBr0CA;;EAWM,wBAA4C;AhB+zClD;;AgB1zCA;;;;EAKI,SAAS;AhB4zCb;;AgBpzCA;EAEI,qCb1DW;AHg3Cf;;AKr3CE;EW2EI,cbvEY;EawEZ,sCbvES;AHq3Cf;;AiBj4CE;;;EAII,yBC2E4D;AlBwzClE;;AiBv4CE;;;;EAYM,qBCmE0D;AlB+zClE;;AKv4CE;EYiBM,yBAJsC;AjB83C9C;;AiB/3CE;;EASQ,yBARoC;AjBm4C9C;;AiBv5CE;;;EAII,yBC2E4D;AlB80ClE;;AiB75CE;;;;EAYM,qBCmE0D;AlBq1ClE;;AK75CE;EYiBM,yBAJsC;AjBo5C9C;;AiBr5CE;;EASQ,yBARoC;AjBy5C9C;;AiB76CE;;;EAII,yBC2E4D;AlBo2ClE;;AiBn7CE;;;;EAYM,qBCmE0D;AlB22ClE;;AKn7CE;EYiBM,yBAJsC;AjB06C9C;;AiB36CE;;EASQ,yBARoC;AjB+6C9C;;AiBn8CE;;;EAII,yBC2E4D;AlB03ClE;;AiBz8CE;;;;EAYM,qBCmE0D;AlBi4ClE;;AKz8CE;EYiBM,yBAJsC;AjBg8C9C;;AiBj8CE;;EASQ,yBARoC;AjBq8C9C;;AiBz9CE;;;EAII,yBC2E4D;AlBg5ClE;;AiB/9CE;;;;EAYM,qBCmE0D;AlBu5ClE;;AK/9CE;EYiBM,yBAJsC;AjBs9C9C;;AiBv9CE;;EASQ,yBARoC;AjB29C9C;;AiB/+CE;;;EAII,yBC2E4D;AlBs6ClE;;AiBr/CE;;;;EAYM,qBCmE0D;AlB66ClE;;AKr/CE;EYiBM,yBAJsC;AjB4+C9C;;AiB7+CE;;EASQ,yBARoC;AjBi/C9C;;AiBrgDE;;;EAII,yBC2E4D;AlB47ClE;;AiB3gDE;;;;EAYM,qBCmE0D;AlBm8ClE;;AK3gDE;EYiBM,yBAJsC;AjBkgD9C;;AiBngDE;;EASQ,yBARoC;AjBugD9C;;AiB3hDE;;;EAII,yBC2E4D;AlBk9ClE;;AiBjiDE;;;;EAYM,qBCmE0D;AlBy9ClE;;AKjiDE;EYiBM,yBAJsC;AjBwhD9C;;AiBzhDE;;EASQ,yBARoC;AjB6hD9C;;AiBjjDE;;;EAII,sCdQS;AH2iDf;;AKhjDE;EYiBM,sCAJsC;AjBuiD9C;;AiBxiDE;;EASQ,sCARoC;AjB4iD9C;;AgBt9CA;EAGM,Wb3GS;Ea4GT,yBbpGY;EaqGZ,qBb2PqD;AH4tC3D;;AgB59CA;EAWM,cb5GY;Ea6GZ,yBblHY;EamHZ,qBblHY;AHukDlB;;AgBh9CA;EACE,Wb3Ha;Ea4Hb,yBbpHgB;AHukDlB;;AgBr9CA;;;EAOI,qBbuOuD;AH6uC3D;;AgB39CA;EAWI,SAAS;AhBo9Cb;;AgB/9CA;EAgBM,2Cb1IS;AH6lDf;;AKxlDE;EW4IM,WbjJO;EakJP,4CblJO;AHkmDf;;AchiDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhBk8CvC;EgBv8CG;IASK,SAAS;EhBi8CjB;AACF;;Ac5iDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhB88CvC;EgBn9CG;IASK,SAAS;EhB68CjB;AACF;;AcxjDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhB09CvC;EgB/9CG;IASK,SAAS;EhBy9CjB;AACF;;AcpkDI;EEiGA;IAEI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,iCAAiC;EhBs+CvC;EgB3+CG;IASK,SAAS;EhBq+CjB;AACF;;AgBp/CA;EAOQ,cAAc;EACd,WAAW;EACX,gBAAgB;EAChB,iCAAiC;AhBi/CzC;;AgB3/CA;EAcU,SAAS;AhBi/CnB;;AmB9pDA;EACE,cAAc;EACd,WAAW;EACX,mChBqe2H;EgBpe3H,yBhBqXkC;EChQ9B,eAtCY;Ee5EhB,gBhB8Q+B;EgB7Q/B,gBhBkR+B;EgBjR/B,chBDgB;EgBEhB,sBhBTa;EgBUb,4BAA4B;EAC5B,yBhBPgB;EONd,sBPqOgC;EiBpO9B,wEjB4e4F;AHksClG;;AoBzqDI;EDLJ;ICMM,gBAAgB;EpB6qDpB;AACF;;AmBprDA;EAsBI,6BAA6B;EAC7B,SAAS;AnBkqDb;;AqBlrDE;EACE,clBAc;EkBCd,sBlBRW;EkBSX,qBlBgdsE;EkB/ctE,UAAU;EAKR,gDlBcW;AHmqDjB;;AmBjsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA+BI,chBxBc;EgB0Bd,UAAU;AnBqqDd;;AmBtsDA;EA2CI,yBhBxCc;EgB0Cd,UAAU;AnB8pDd;;AmB1pDA;EAOI,chBhDc;EgBiDd,sBhBxDW;AH+sDf;;AmBlpDA;;EAEE,cAAc;EACd,WAAW;AnBqpDb;;AmB3oDA;EACE,iCAA+D;EAC/D,oCAAkE;EAClE,gBAAgB;EfZd,kBAAW;Eecb,gBhB0M+B;AHo8CjC;;AmB3oDA;EACE,+BAAkE;EAClE,kCAAqE;EfoCjE,kBAtCY;EeIhB,gBhBuI+B;AHugDjC;;AmB3oDA;EACE,gCAAkE;EAClE,mCAAqE;Ef6BjE,mBAtCY;EeWhB,gBhBiI+B;AH6gDjC;;AmBroDA;EACE,cAAc;EACd,WAAW;EACX,qBhB8QmC;EgB7QnC,wBhB6QmC;EgB5QnC,gBAAgB;EAChB,gBhB6K+B;EgB5K/B,chBpGgB;EgBqGhB,6BAA6B;EAC7B,yBAAyB;EACzB,mBAAmC;AnBwoDrC;;AmBlpDA;EAcI,gBAAgB;EAChB,eAAe;AnBwoDnB;;AmB5nDA;EACE,kChBsWqI;EgBrWrI,uBhB+PiC;EC1Q7B,mBAtCY;EemDhB,gBhByF+B;EOhO7B,qBPuO+B;AHgiDnC;;AmB5nDA;EACE,gChB+VqI;EgB9VrI,oBhB4PgC;EC/Q5B,kBAtCY;Ee2DhB,gBhBgF+B;EO/N7B,qBPsO+B;AHyiDnC;;AmB3nDA;EAGI,YAAY;AnB4nDhB;;AmBxnDA;EACE,YAAY;AnB2nDd;;AmBnnDA;EACE,mBhBoV0C;AHkyC5C;;AmBnnDA;EACE,cAAc;EACd,mBhBqU4C;AHizC9C;;AmB9mDA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,kBAA0C;EAC1C,iBAAyC;AnBinD3C;;AmBrnDA;;EAQI,kBAA0C;EAC1C,iBAAyC;AnBknD7C;;AmBzmDA;EACE,kBAAkB;EAClB,cAAc;EACd,qBhB0S6C;AHk0C/C;;AmBzmDA;EACE,kBAAkB;EAClB,kBhBsS2C;EgBrS3C,qBhBoS6C;AHw0C/C;;AmB/mDA;EAMI,chBxMc;AHqzDlB;;AmBzmDA;EACE,gBAAgB;AnB4mDlB;;AmBzmDA;EACE,2BAAoB;EAApB,oBAAoB;EACpB,sBAAmB;EAAnB,mBAAmB;EACnB,eAAe;EACf,qBhByR4C;AHm1C9C;;AmBhnDA;EAQI,gBAAgB;EAChB,aAAa;EACb,uBhBoR4C;EgBnR5C,cAAc;AnB4mDlB;;AqBvzDE;EACE,aAAa;EACb,WAAW;EACX,mBlBod0C;EC5a1C,cAAW;EiBtCX,clBSa;AHizDjB;;AqBvzDE;EACE,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe;EACf,uBlBsyBqC;EkBryBrC,iBAAiB;EjBmFf,mBAtCY;EiB3Cd,gBlBkP6B;EkBjP7B,WlBxCW;EkByCX,wClBLa;EOtCb,sBPqOgC;AHioDpC;;AqBtzDI;EAEE,qBlBZW;EkBeT,oClBgb2F;EkB/a3F,4PHfmI;EGgBnI,4BAA4B;EAC5B,2DlB+a6F;EkB9a7F,gElB6awF;AHy4ChG;;AqB/zDI;EAaI,qBlBvBS;EkBwBT,gDlBxBS;AH80DjB;;AqBp0DI;;;EAmBI,cAAc;ArBuzDtB;;AqBhzDI;EAGI,oClBwZ2F;EkBvZ3F,kFlByZ6F;AHw5CrG;;AqB3yDI;EAEE,qBlBhDW;EkBmDT,sDlBqe0J;EkBpe1J,6gBAAkJ;ArB2yD1J;;AqBjzDI;EAUI,qBlBxDS;EkByDT,gDlBzDS;AHo2DjB;;AqBtzDI;;;EAgBI,cAAc;ArB4yDtB;;AqBryDI;;;EAII,cAAc;ArBuyDtB;;AqBjyDI;EAGI,clBlFS;AHo3DjB;;AqBryDI;;;EAQI,cAAc;ArBmyDtB;;AqB7xDI;EAGI,clBhGS;AH83DjB;;AqBjyDI;EAMM,qBlBnGO;AHk4DjB;;AqBryDI;;;EAYI,cAAc;ArB+xDtB;;AqB3yDI;EAiBM,qBAAkC;ECnJxC,yBDoJ+C;ArB8xDnD;;AqBhzDI;EAwBM,gDlBrHO;AHi5DjB;;AqBpzDI;EA4BM,qBlBzHO;AHq5DjB;;AqBpxDI;EAGI,qBlBpIS;AHy5DjB;;AqBxxDI;;;EAQI,cAAc;ArBsxDtB;;AqB9xDI;EAaM,qBlB9IO;EkB+IP,gDlB/IO;AHo6DjB;;AqBl7DE;EACE,aAAa;EACb,WAAW;EACX,mBlBod0C;EC5a1C,cAAW;EiBtCX,clBMa;AH+6DjB;;AqBl7DE;EACE,kBAAkB;EAClB,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe;EACf,uBlBsyBqC;EkBryBrC,iBAAiB;EjBmFf,mBAtCY;EiB3Cd,gBlBkP6B;EkBjP7B,WlBxCW;EkByCX,wClBRa;EOnCb,sBPqOgC;AH4vDpC;;AqBj7DI;EAEE,qBlBfW;EkBkBT,oClBgb2F;EkB/a3F,sSHfmI;EGgBnI,4BAA4B;EAC5B,2DlB+a6F;EkB9a7F,gElB6awF;AHogDhG;;AqB17DI;EAaI,qBlB1BS;EkB2BT,gDlB3BS;AH48DjB;;AqB/7DI;;;EAmBI,cAAc;ArBk7DtB;;AqB36DI;EAGI,oClBwZ2F;EkBvZ3F,kFlByZ6F;AHmhDrG;;AqBt6DI;EAEE,qBlBnDW;EkBsDT,sDlBqe0J;EkBpe1J,ujBAAkJ;ArBs6D1J;;AqB56DI;EAUI,qBlB3DS;EkB4DT,gDlB5DS;AHk+DjB;;AqBj7DI;;;EAgBI,cAAc;ArBu6DtB;;AqBh6DI;;;EAII,cAAc;ArBk6DtB;;AqB55DI;EAGI,clBrFS;AHk/DjB;;AqBh6DI;;;EAQI,cAAc;ArB85DtB;;AqBx5DI;EAGI,clBnGS;AH4/DjB;;AqB55DI;EAMM,qBlBtGO;AHggEjB;;AqBh6DI;;;EAYI,cAAc;ArB05DtB;;AqBt6DI;EAiBM,qBAAkC;ECnJxC,yBDoJ+C;ArBy5DnD;;AqB36DI;EAwBM,gDlBxHO;AH+gEjB;;AqB/6DI;EA4BM,qBlB5HO;AHmhEjB;;AqB/4DI;EAGI,qBlBvIS;AHuhEjB;;AqBn5DI;;;EAQI,cAAc;ArBi5DtB;;AqBz5DI;EAaM,qBlBjJO;EkBkJP,gDlBlJO;AHkiEjB;;AmBz0DA;EACE,oBAAa;EAAb,aAAa;EACb,uBAAmB;EAAnB,mBAAmB;EACnB,sBAAmB;EAAnB,mBAAmB;AnB40DrB;;AmB/0DA;EASI,WAAW;AnB00Df;;AcxhEI;EKqMJ;IAeM,oBAAa;IAAb,aAAa;IACb,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;IACvB,gBAAgB;EnBy0DpB;EmB31DF;IAuBM,oBAAa;IAAb,aAAa;IACb,kBAAc;IAAd,cAAc;IACd,uBAAmB;IAAnB,mBAAmB;IACnB,sBAAmB;IAAnB,mBAAmB;IACnB,gBAAgB;EnBu0DpB;EmBl2DF;IAgCM,qBAAqB;IACrB,WAAW;IACX,sBAAsB;EnBq0D1B;EmBv2DF;IAuCM,qBAAqB;EnBm0DzB;EmB12DF;;IA4CM,WAAW;EnBk0Df;EmB92DF;IAkDM,oBAAa;IAAb,aAAa;IACb,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;IACvB,WAAW;IACX,eAAe;EnB+zDnB;EmBr3DF;IAyDM,kBAAkB;IAClB,oBAAc;IAAd,cAAc;IACd,aAAa;IACb,qBhB2LwC;IgB1LxC,cAAc;EnB+zDlB;EmB53DF;IAiEM,sBAAmB;IAAnB,mBAAmB;IACnB,qBAAuB;IAAvB,uBAAuB;EnB8zD3B;EmBh4DF;IAqEM,gBAAgB;EnB8zDpB;AACF;;AuB/nEA;EACE,qBAAqB;EAErB,gBpBkR+B;EoBjR/B,cpBMgB;EoBLhB,kBAAkB;EAClB,sBAAsB;EACtB,yBAAiB;EAAjB,sBAAiB;EAAjB,qBAAiB;EAAjB,iBAAiB;EACjB,6BAA6B;EAC7B,6BAA2C;ECsF3C,yBrB0RkC;EChQ9B,eAtCY;EoBchB,gBrByL+B;EO3R7B,sBPqOgC;EiBpO9B,qIjBqb6I;AH0tDnJ;;AoB1oEI;EGLJ;IHMM,gBAAgB;EpB8oEpB;AACF;;AK/oEE;EkBQE,cpBJc;EoBKd,qBAAqB;AvB2oEzB;;AuB1pEA;EAoBI,UAAU;EACV,gDpBSa;AHioEjB;;AuB/pEA;EA2BI,apB8Y6B;AH0vDjC;;AuBznEA;;EAEE,oBAAoB;AvB4nEtB;;AuBnnEE;ECrDA,WrBCa;EmBDX,yBnB8Ba;EqB5Bf,qBrB4Be;AHgpEjB;;AKxqEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxBqrE7H;;AwBzqEE;EAMI,gDAAiF;AxBuqEvF;;AwBlqEE;EAEE,WrBvBW;EqBwBX,yBrBKa;EqBJb,qBrBIa;AHgqEjB;;AwB7pEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBssEnN;;AwB1pEI;;EAKI,gDAAiF;AxB0pEzF;;AuBrpEE;ECrDA,WrBCa;EmBDX,yBnBOc;EqBLhB,qBrBKgB;AHysElB;;AK1sEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxButE7H;;AwB3sEE;EAMI,iDAAiF;AxBysEvF;;AwBpsEE;EAEE,WrBvBW;EqBwBX,yBrBlBc;EqBmBd,qBrBnBc;AHytElB;;AwB/rEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBwuEnN;;AwB5rEI;;EAKI,iDAAiF;AxB4rEzF;;AuBvrEE;ECrDA,WrBCa;EmBDX,yBnBqCa;EqBnCf,qBrBmCe;AH6sEjB;;AK5uEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxByvE7H;;AwB7uEE;EAMI,+CAAiF;AxB2uEvF;;AwBtuEE;EAEE,WrBvBW;EqBwBX,yBrBYa;EqBXb,qBrBWa;AH6tEjB;;AwBjuEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxB0wEnN;;AwB9tEI;;EAKI,+CAAiF;AxB8tEzF;;AuBztEE;ECrDA,WrBCa;EmBDX,yBnBuCa;EqBrCf,qBrBqCe;AH6uEjB;;AK9wEE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxB2xE7H;;AwB/wEE;EAMI,gDAAiF;AxB6wEvF;;AwBxwEE;EAEE,WrBvBW;EqBwBX,yBrBca;EqBbb,qBrBaa;AH6vEjB;;AwBnwEE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxB4yEnN;;AwBhwEI;;EAKI,gDAAiF;AxBgwEzF;;AuB3vEE;ECrDA,crBUgB;EmBVd,yBnBoCa;EqBlCf,qBrBkCe;AHkxEjB;;AKhzEE;EmBAE,crBIc;EmBVd,yBEDoF;EASpF,qBATyH;AxB6zE7H;;AwBjzEE;EAMI,gDAAiF;AxB+yEvF;;AwB1yEE;EAEE,crBdc;EqBed,yBrBWa;EqBVb,qBrBUa;AHkyEjB;;AwBryEE;;EAGE,crB1Bc;EqB2Bd,yBAtCuK;EA0CvK,qBA1C+M;AxB80EnN;;AwBlyEI;;EAKI,gDAAiF;AxBkyEzF;;AuB7xEE;ECrDA,WrBCa;EmBDX,yBnBkCa;EqBhCf,qBrBgCe;AHszEjB;;AKl1EE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxB+1E7H;;AwBn1EE;EAMI,+CAAiF;AxBi1EvF;;AwB50EE;EAEE,WrBvBW;EqBwBX,yBrBSa;EqBRb,qBrBQa;AHs0EjB;;AwBv0EE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBg3EnN;;AwBp0EI;;EAKI,+CAAiF;AxBo0EzF;;AuB/zEE;ECrDA,crBUgB;EmBVd,yBnBEc;EqBAhB,qBrBAgB;AHw3ElB;;AKp3EE;EmBAE,crBIc;EmBVd,yBEDoF;EASpF,qBATyH;AxBi4E7H;;AwBr3EE;EAMI,iDAAiF;AxBm3EvF;;AwB92EE;EAEE,crBdc;EqBed,yBrBvBc;EqBwBd,qBrBxBc;AHw4ElB;;AwBz2EE;;EAGE,crB1Bc;EqB2Bd,yBAtCuK;EA0CvK,qBA1C+M;AxBk5EnN;;AwBt2EI;;EAKI,iDAAiF;AxBs2EzF;;AuBj2EE;ECrDA,WrBCa;EmBDX,yBnBSc;EqBPhB,qBrBOgB;AHm5ElB;;AKt5EE;EmBAE,WrBLW;EmBDX,yBEDoF;EASpF,qBATyH;AxBm6E7H;;AwBv5EE;EAMI,8CAAiF;AxBq5EvF;;AwBh5EE;EAEE,WrBvBW;EqBwBX,yBrBhBc;EqBiBd,qBrBjBc;AHm6ElB;;AwB34EE;;EAGE,WrBnCW;EqBoCX,yBAtCuK;EA0CvK,qBA1C+M;AxBo7EnN;;AwBx4EI;;EAKI,8CAAiF;AxBw4EzF;;AuB73EE;ECJA,crBzBe;EqB0Bf,qBrB1Be;AH+5EjB;;AKv7EE;EmBqDE,WrB1DW;EqB2DX,yBrB9Ba;EqB+Bb,qBrB/Ba;AHq6EjB;;AwBn4EE;EAEE,+CrBpCa;AHy6EjB;;AwBl4EE;EAEE,crBzCa;EqB0Cb,6BAA6B;AxBo4EjC;;AwBj4EE;;EAGE,WrB7EW;EqB8EX,yBrBjDa;EqBkDb,qBrBlDa;AHq7EjB;;AwBj4EI;;EAKI,+CrBzDS;AH07EjB;;AuB75EE;ECJA,crBhDgB;EqBiDhB,qBrBjDgB;AHs9ElB;;AKv9EE;EmBqDE,WrB1DW;EqB2DX,yBrBrDc;EqBsDd,qBrBtDc;AH49ElB;;AwBn6EE;EAEE,iDrB3Dc;AHg+ElB;;AwBl6EE;EAEE,crBhEc;EqBiEd,6BAA6B;AxBo6EjC;;AwBj6EE;;EAGE,WrB7EW;EqB8EX,yBrBxEc;EqByEd,qBrBzEc;AH4+ElB;;AwBj6EI;;EAKI,iDrBhFU;AHi/ElB;;AuB77EE;ECJA,crBlBe;EqBmBf,qBrBnBe;AHw9EjB;;AKv/EE;EmBqDE,WrB1DW;EqB2DX,yBrBvBa;EqBwBb,qBrBxBa;AH89EjB;;AwBn8EE;EAEE,+CrB7Ba;AHk+EjB;;AwBl8EE;EAEE,crBlCa;EqBmCb,6BAA6B;AxBo8EjC;;AwBj8EE;;EAGE,WrB7EW;EqB8EX,yBrB1Ca;EqB2Cb,qBrB3Ca;AH8+EjB;;AwBj8EI;;EAKI,+CrBlDS;AHm/EjB;;AuB79EE;ECJA,crBhBe;EqBiBf,qBrBjBe;AHs/EjB;;AKvhFE;EmBqDE,WrB1DW;EqB2DX,yBrBrBa;EqBsBb,qBrBtBa;AH4/EjB;;AwBn+EE;EAEE,gDrB3Ba;AHggFjB;;AwBl+EE;EAEE,crBhCa;EqBiCb,6BAA6B;AxBo+EjC;;AwBj+EE;;EAGE,WrB7EW;EqB8EX,yBrBxCa;EqByCb,qBrBzCa;AH4gFjB;;AwBj+EI;;EAKI,gDrBhDS;AHihFjB;;AuB7/EE;ECJA,crBnBe;EqBoBf,qBrBpBe;AHyhFjB;;AKvjFE;EmBqDE,crBjDc;EqBkDd,yBrBxBa;EqByBb,qBrBzBa;AH+hFjB;;AwBngFE;EAEE,+CrB9Ba;AHmiFjB;;AwBlgFE;EAEE,crBnCa;EqBoCb,6BAA6B;AxBogFjC;;AwBjgFE;;EAGE,crBpEc;EqBqEd,yBrB3Ca;EqB4Cb,qBrB5Ca;AH+iFjB;;AwBjgFI;;EAKI,+CrBnDS;AHojFjB;;AuB7hFE;ECJA,crBrBe;EqBsBf,qBrBtBe;AH2jFjB;;AKvlFE;EmBqDE,WrB1DW;EqB2DX,yBrB1Ba;EqB2Bb,qBrB3Ba;AHikFjB;;AwBniFE;EAEE,+CrBhCa;AHqkFjB;;AwBliFE;EAEE,crBrCa;EqBsCb,6BAA6B;AxBoiFjC;;AwBjiFE;;EAGE,WrB7EW;EqB8EX,yBrB7Ca;EqB8Cb,qBrB9Ca;AHilFjB;;AwBjiFI;;EAKI,+CrBrDS;AHslFjB;;AuB7jFE;ECJA,crBrDgB;EqBsDhB,qBrBtDgB;AH2nFlB;;AKvnFE;EmBqDE,crBjDc;EqBkDd,yBrB1Dc;EqB2Dd,qBrB3Dc;AHioFlB;;AwBnkFE;EAEE,iDrBhEc;AHqoFlB;;AwBlkFE;EAEE,crBrEc;EqBsEd,6BAA6B;AxBokFjC;;AwBjkFE;;EAGE,crBpEc;EqBqEd,yBrB7Ec;EqB8Ed,qBrB9Ec;AHipFlB;;AwBjkFI;;EAKI,iDrBrFU;AHspFlB;;AuB7lFE;ECJA,crB9CgB;EqB+ChB,qBrB/CgB;AHopFlB;;AKvpFE;EmBqDE,WrB1DW;EqB2DX,yBrBnDc;EqBoDd,qBrBpDc;AH0pFlB;;AwBnmFE;EAEE,8CrBzDc;AH8pFlB;;AwBlmFE;EAEE,crB9Dc;EqB+Dd,6BAA6B;AxBomFjC;;AwBjmFE;;EAGE,WrB7EW;EqB8EX,yBrBtEc;EqBuEd,qBrBvEc;AH0qFlB;;AwBjmFI;;EAKI,8CrB9EU;AH+qFlB;;AuBlnFA;EACE,gBpB8M+B;EoB7M/B,cpB1Ce;EoB2Cf,qBpB6F4C;AHwhF9C;;AKxrFE;EkBsEE,cpB2F8D;EoB1F9D,0BpB2F+C;AH2hFnD;;AuB7nFA;EAYI,0BpBsF+C;EoBrF/C,gBAAgB;AvBqnFpB;;AuBloFA;EAkBI,cpBjFc;EoBkFd,oBAAoB;AvBonFxB;;AuBzmFA;ECLE,oBrBySgC;EC/Q5B,kBAtCY;EoBchB,gBrB6H+B;EO/N7B,qBPsO+B;AH++EnC;;AuB5mFA;ECTE,uBrBoSiC;EC1Q7B,mBAtCY;EoBchB,gBrB8H+B;EOhO7B,qBPuO+B;AHq/EnC;;AuB1mFA;EACE,cAAc;EACd,WAAW;AvB6mFb;;AuB/mFA;EAMI,kBpBuT+B;AHszEnC;;AuBxmFA;;;EAII,WAAW;AvB0mFf;;AyBhvFA;ELMM,gCjBsP2C;AHw/EjD;;AoBzuFI;EKXJ;ILYM,gBAAgB;EpB6uFpB;AACF;;Ay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CT,gBAAgB;A9B0nGpB;;A8B1oGA;;;;;;;;;;;;EAqBM,iB3B4M2B;AHw7FjC;;A8BzpGA;;;EA6BI,UAAU;A9BkoGd;;A8B/pGA;EAkCI,UAAU;A9BioGd;;A8BnqGA;;EpBeI,0BoBwBmD;EpBvBnD,6BoBuBmD;A9BkoGvD;;A8BzqGA;;EpB6BI,yBoBWmD;EpBVnD,4BoBUmD;A9BuoGvD;;A8B/qGA;EA8CI,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;A9BqoGvB;;A8BprGA;;EpBeI,0BoBmC6E;EpBlC7E,6BoBkC6E;A9BwoGjF;;A8B1rGA;EpB6BI,yBoBsBsE;EpBrBtE,4BoBqBsE;A9B4oG1E;;A8BjoGA;;EAEE,oBAAa;EAAb,aAAa;A9BooGf;;A8BtoGA;;EAQI,kBAAkB;EAClB,UAAU;A9BmoGd;;A8B5oGA;;EAYM,UAAU;A9BqoGhB;;A8BjpGA;;;;;;;;EAoBI,iB3B+I6B;AHy/FjC;;A8BpoGA;EAAuB,kB3B2IU;AH6/FjC;;A8BvoGA;EAAsB,iB3B0IW;AHigGjC;;A8BnoGA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,yB3BuRkC;E2BtRlC,gBAAgB;E1BsBZ,eAtCY;E0BkBhB,gB3BgL+B;E2B/K/B,gB3BoL+B;E2BnL/B,c3B/FgB;E2BgGhB,kBAAkB;EAClB,mBAAmB;EACnB,yB3BvGgB;E2BwGhB,yB3BtGgB;EONd,sBPqOgC;AH8gGpC;;A8BnpGA;;EAkBI,aAAa;A9BsoGjB;;A8B5nGA;;EAEE,gC3B6WqI;AHkxFvI;;A8B5nGA;;;;;;EAME,oB3BkQgC;EC/Q5B,kBAtCY;E0BqDhB,gB3BsF+B;EO/N7B,qBPsO+B;AHmiGnC;;A8B5nGA;;EAEE,kC3B2VqI;AHoyFvI;;A8B5nGA;;;;;;EAME,uB3B4OiC;EC1Q7B,mBAtCY;E0BsEhB,gB3BsE+B;EOhO7B,qBPuO+B;AHmjGnC;;A8B5nGA;;EAEE,sBAA0E;A9B+nG5E;;A8BpnGA;;;;;;EpB3JI,0BoBiK4B;EpBhK5B,6BoBgK4B;A9BwnGhC;;A8BrnGA;;;;;;EpBtJI,yBoB4J2B;EpB3J3B,4BoB2J2B;A9BynG/B;;A+B/yGA;EACE,kBAAkB;EAClB,cAAc;EACd,kBAA+C;EAC/C,oBAAqE;A/BkzGvE;;A+B/yGA;EACE,2BAAoB;EAApB,oBAAoB;EACpB,kB5Bqf0C;AH6zF5C;;A+B/yGA;EACE,kBAAkB;EAClB,WAAW;EACX,UAAU;A/BkzGZ;;A+BrzGA;EAMI,W5BpBW;E4BqBX,qB5BQa;EmB9Bb,yBnB8Ba;AH4yGjB;;A+B3zGA;EAiBM,gD5BFW;AHgzGjB;;A+B/zGA;EAsBI,qB5BqbsE;AHw3F1E;;A+Bn0GA;EA0BI,W5BxCW;E4ByCX,yB5B8e8E;E4B7e9E,qB5B6e8E;AHg0FlF;;A+Bz0GA;EAkCM,c5B1CY;AHq1GlB;;A+B70GA;EAqCQ,yB5BjDU;AH61GlB;;A+BlyGA;EACE,kBAAkB;EAClB,gBAAgB;EAChB,mBAAmB;A/BqyGrB;;A+BxyGA;EAOI,kBAAkB;EAClB,YAA+E;EAC/E,aAA+D;EAC/D,cAAc;EACd,W5B0bwC;E4BzbxC,Y5BybwC;E4BxbxC,oBAAoB;EACpB,WAAW;EACX,sB5B5EW;E4B6EX,yB5BmJ6B;AHkpGjC;;A+BrzGA;EAsBI,kBAAkB;EAClB,YAA+E;EAC/E,aAA+D;EAC/D,cAAc;EACd,W5B2awC;E4B1axC,Y5B0awC;E4BzaxC,WAAW;EACX,mCAAgE;A/BmyGpE;;A+B1xGA;ErBrGI,sBPqOgC;AH8pGpC;;A+B9xGA;EAOM,6MbrEqI;AlBg2G3I;;A+BlyGA;EAaM,qB5BnFW;EmB9Bb,yBnB8Ba;AH62GjB;;A+BvyGA;EAkBM,0JbhFqI;AlBy2G3I;;A+B3yGA;EAwBM,wC5B9FW;AHq3GjB;;A+B/yGA;EA2BM,wC5BjGW;AHy3GjB;;A+B/wGA;EAGI,kB5B0Z+C;AHs3FnD;;A+BnxGA;EAQM,uJb1GqI;AlBy3G3I;;A+BvxGA;EAcM,wC5BxHW;AHq4GjB;;A+BnwGA;EACE,qBAA2D;A/BswG7D;;A+BvwGA;EAKM,cAAqD;EACrD,c5BkY+E;E4BjY/E,mBAAmB;EAEnB,qB5BgY4E;AHq4FlF;;A+B9wGA;EAaM,wBAA0I;EAC1I,0BAA+G;EAC/G,uB5B2XiI;E4B1XjI,wB5B0XiI;E4BzXjI,yB5B3KY;E4B6KZ,qB5BsX4E;EiBziB5E,iJjB8f+H;EiB9f/H,yIjB8f+H;EiB9f/H,8KjB8f+H;AH07FrI;;AoBn7GI;EW2JJ;IX1JM,gBAAgB;EpBu7GpB;AACF;;A+B9xGA;EA0BM,sB5BzLS;E4B0LT,sCAA4E;EAA5E,8BAA4E;A/BwwGlF;;A+BnyGA;EAiCM,wC5BnKW;AHy6GjB;;A+B1vGA;EACE,qBAAqB;EACrB,WAAW;EACX,mC5BwR2H;E4BvR3H,0C5BwKkC;EChQ9B,eAtCY;E2BiIhB,gB5BiE+B;E4BhE/B,gB5BqE+B;E4BpE/B,c5B9MgB;E4B+MhB,sBAAsB;EACtB,6M5BmWmI;E4BlWnI,sB5BxNa;E4ByNb,yB5BrNgB;EONd,sBPqOgC;E4BPlC,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/B2vGlB;;A+B3wGA;EAmBI,qB5B0PsE;E4BzPtE,UAAU;EAIR,gD5BvMW;AHg8GjB;;A+BjxGA;EAiCM,c5BtOY;E4BuOZ,sB5B9OS;AHk+Gf;;A+BtxGA;EAwCI,YAAY;EACZ,sB5BmIgC;E4BlIhC,sBAAsB;A/BkvG1B;;A+B5xGA;EA8CI,c5BpPc;E4BqPd,yB5BzPc;AH2+GlB;;A+BjyGA;EAoDI,aAAa;A/BivGjB;;A+B7uGA;EACE,kC5BmOqI;E4BlOrI,oB5B2HkC;E4B1HlC,uB5B0HkC;E4BzHlC,oB5B0HiC;EC1Q7B,mBAtCY;AJu6GlB;;A+B7uGA;EACE,gC5B4NqI;E4B3NrI,mB5BwHiC;E4BvHjC,sB5BuHiC;E4BtHjC,kB5BuHgC;EC/Q5B,kBAtCY;AJ+6GlB;;A+BxuGA;EACE,kBAAkB;EAClB,qBAAqB;EACrB,WAAW;EACX,mC5B0M2H;E4BzM3H,gBAAgB;A/B2uGlB;;A+BxuGA;EACE,kBAAkB;EAClB,UAAU;EACV,WAAW;EACX,mC5BkM2H;E4BjM3H,SAAS;EACT,UAAU;A/B2uGZ;;A+BjvGA;EASI,qB5B+KsE;E4B9KtE,gD5B9Qa;AH0/GjB;;A+BtvGA;EAcI,yB5B7Sc;AHyhHlB;;A+B1vGA;EAmBM,iB5BqUQ;AHs6Fd;;A+B9vGA;EAwBI,0BAA0B;A/B0uG9B;;A+BtuGA;EACE,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,OAAO;EACP,UAAU;EACV,mC5BoK2H;E4BnK3H,yB5BoDkC;E4BlDlC,gB5BlD+B;E4BmD/B,gB5B9C+B;E4B+C/B,c5BjUgB;E4BkUhB,sB5BzUa;E4B0Ub,yB5BtUgB;EONd,sBPqOgC;AHg1GpC;;A+BtvGA;EAkBI,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,SAAS;EACT,UAAU;EACV,cAAc;EACd,6B5B8I+F;E4B7I/F,yB5BkCgC;E4BjChC,gB5B9D6B;E4B+D7B,c5BjVc;E4BkVd,iBAAiB;ET1VjB,yBnBGc;E4ByVd,oBAAoB;ErB7VpB,kCqB8VgF;A/BwuGpF;;A+B9tGA;EACE,WAAW;EACX,2BAA+F;EAC/F,UAAU;EACV,6BAA6B;EAC7B,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/BiuGlB;;A+BtuGA;EAQI,aAAa;A/BkuGjB;;A+B1uGA;EAY8B,gE5BrVb;AHujHjB;;A+B9uGA;EAa8B,gE5BtVb;AH2jHjB;;A+BlvGA;EAc8B,gE5BvVb;AH+jHjB;;A+BtvGA;EAkBI,SAAS;A/BwuGb;;A+B1vGA;EAsBI,W5B8N6C;E4B7N7C,Y5B6N6C;E4B5N7C,oBAAyE;ET/XzE,yBnB8Ba;E4BmWb,S5B6N0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4BzHjI,wBAAgB;EAAhB,gBAAgB;A/BuuGpB;;AoBvmHI;EWkWJ;IXjWM,gBAAgB;EpB2mHpB;AACF;;A+B3wGA;ETvWI,yBnBmmB2E;AHmhG/E;;A+B/wGA;EAsCI,W5BuMoC;E4BtMpC,c5BuMqC;E4BtMrC,kBAAkB;EAClB,e5BsMuC;E4BrMvC,yB5B7Yc;E4B8Yd,yBAAyB;ErBnZzB,mBPylBoC;AHwiGxC;;A+BzxGA;EAiDI,W5BmM6C;E4BlM7C,Y5BkM6C;EmB3lB7C,yBnB8Ba;E4B6Xb,S5BmM0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4B/FjI,qBAAgB;EAAhB,gBAAgB;A/B2uGpB;;AoBroHI;EWkWJ;IXjWM,gBAAgB;EpByoHpB;AACF;;A+BzyGA;ETvWI,yBnBmmB2E;AHijG/E;;A+B7yGA;EAgEI,W5B6KoC;E4B5KpC,c5B6KqC;E4B5KrC,kBAAkB;EAClB,e5B4KuC;E4B3KvC,yB5Bvac;E4Bwad,yBAAyB;ErB7azB,mBPylBoC;AHskGxC;;A+BvzGA;EA2EI,W5ByK6C;E4BxK7C,Y5BwK6C;E4BvK7C,aAAa;EACb,oB5BvD+B;E4BwD/B,mB5BxD+B;EmB9X/B,yBnB8Ba;E4B0Zb,S5BsK0C;EO/lB1C,mBPgmB6C;EiB/lB3C,4GjB8f+H;E4BlEjI,gBAAgB;A/B+uGpB;;AoBtqHI;EWkWJ;IXjWM,gBAAgB;EpB0qHpB;AACF;;A+B10GA;ETvWI,yBnBmmB2E;AHklG/E;;A+B90GA;EA6FI,W5BgJoC;E4B/IpC,c5BgJqC;E4B/IrC,kBAAkB;EAClB,e5B+IuC;E4B9IvC,6BAA6B;EAC7B,yBAAyB;EACzB,oBAA4C;A/BqvGhD;;A+Bx1GA;EAwGI,yB5B3cc;EOLd,mBPylBoC;AH4mGxC;;A+B71GA;EA6GI,kBAAkB;EAClB,yB5Bjdc;EOLd,mBPylBoC;AHknGxC;;A+Bn2GA;EAoHM,yB5BrdY;AHwsHlB;;A+Bv2GA;EAwHM,eAAe;A/BmvGrB;;A+B32GA;EA4HM,yB5B7dY;AHgtHlB;;A+B/2GA;EAgIM,eAAe;A/BmvGrB;;A+Bn3GA;EAoIM,yB5BreY;AHwtHlB;;A+B9uGA;;;EXhfM,4GjB8f+H;AHsuGrI;;AoB/tHI;EW2eJ;;;IX1eM,gBAAgB;EpBquHpB;AACF;;AgC7uHA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;AhCgvHlB;;AgC7uHA;EACE,cAAc;EACd,oB7BkqBsC;AH8kGxC;;AK/uHE;E2BEE,qBAAqB;AhCivHzB;;AgCtvHA;EAUI,c7BVc;E6BWd,oBAAoB;EACpB,eAAe;AhCgvHnB;;AgCxuHA;EACE,gC7BxBgB;AHmwHlB;;AgC5uHA;EAII,mB7BkM6B;AH0iHjC;;AgChvHA;EAQI,6BAAgD;EtB3BhD,+BP4NgC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9BzMS;AH+lIf;;AiCh7HA;EA+BI,yB9B9MW;E8B+MX,gC9B/MW;AHomIf;;AiCr7HA;EAoCI,wP9B6fsR;AHw5G1R;;AiCz7HA;EAwCI,yB9BvNW;AH4mIf;;AiC77HA;EA0CM,yB9BzNS;AHgnIf;;AKjnIE;E4B6NM,yB9B5NO;AHonIf;;AiCj5HA;EAEI,W9B/OW;AHkoIf;;AKznIE;E4ByOI,W9BlPS;AHsoIf;;AiCz5HA;EAWM,+B9BxPS;AH0oIf;;AKjoIE;E4BkPM,gC9B3PO;AH8oIf;;AiCj6HA;EAkBQ,gC9B/PO;AHkpIf;;AiCr6HA;;;;EA0BM,W9BvQS;AHypIf;;AiC56HA;EA+BI,+B9B5QW;E8B6QX,sC9B7QW;AH8pIf;;AiCj7HA;EAoCI,8P9BkcqR;AH+8GzR;;AiCr7HA;EAwCI,+B9BrRW;AHsqIf;;AiCz7HA;EA0CM,W9BvRS;AH0qIf;;AKjqIE;E4BiRM,W9B1RO;AH8qIf;;AkCjrIA;EACE,kBAAkB;EAClB,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,YAAY;EACZ,qBAAqB;EACrB,sB/BHa;E+BIb,2BAA2B;EAC3B,sC/BKa;EOZX,sBPqOgC;AHu9HpC;;AkC7rIA;EAYI,eAAe;EACf,cAAc;AlCqrIlB;;AkClsIA;ExBUI,+BP4NgC;EO3NhC,gCP2NgC;AHi+HpC;;AkCvsIA;ExBwBI,mCP8MgC;EO7MhC,kCP6MgC;AHs+HpC;;AkC/qIA;EAGE,kBAAc;EAAd,cAAc;EACd,gB/B+wByC;AHi6G3C;;AkC5qIA;EACE,sB/BywBwC;AHs6G1C;;AkC5qIA;EACE,qBAA+B;EAC/B,gBAAgB;AlC+qIlB;;AkC5qIA;EACE,gBAAgB;AlC+qIlB;;AKttIE;E6B4CE,qBAAqB;AlC8qIzB;;AkChrIA;EAMI,oB/BwvBuC;AHs7G3C;;AkCtqIA;EACE,wB/B+uByC;E+B9uBzC,gBAAgB;EAEhB,qC/BvDa;E+BwDb,6C/BxDa;AHguIf;;AkC7qIA;ExB/DI,0DwBuE8E;AlCyqIlF;;AkCjrIA;EAaM,aAAa;AlCwqInB;;AkCnqIA;EACE,wB/B6tByC;E+B5tBzC,qC/BvEa;E+BwEb,0C/BxEa;AH8uIf;;AkCzqIA;ExBjFI,0DPmzBoF;AH28GxF;;AkC9pIA;EACE,uBAAiC;EACjC,uB/B4sBwC;E+B3sBxC,sBAAgC;EAChC,gBAAgB;AlCiqIlB;;AkC9pIA;EACE,uBAAiC;EACjC,sBAAgC;AlCiqIlC;;AkC7pIA;EACE,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,SAAS;EACT,OAAO;EACP,gB/BssByC;AH09G3C;;AkC7pIA;EACE,WAAW;ExBvHT,kCPmzBoF;AHq+GxF;;AkC5pIA;EACE,WAAW;ExBpHT,2CP0yBoF;EOzyBpF,4CPyyBoF;AH2+GxF;;AkC7pIA;EACE,WAAW;ExB3GT,+CP4xBoF;EO3xBpF,8CP2xBoF;AHi/GxF;;AkC3pIA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;AlC8pIxB;;AkChqIA;EAKI,mB/B6qBsD;AHk/G1D;;ActvII;EoBkFJ;IASI,uBAAmB;IAAnB,mBAAmB;IACnB,mB/BwqBsD;I+BvqBtD,kB/BuqBsD;EHy/GxD;EkC3qIF;IAcM,oBAAa;IAAb,aAAa;IAEb,gBAAY;IAAZ,YAAY;IACZ,0BAAsB;IAAtB,sBAAsB;IACtB,kB/BgqBoD;I+B/pBpD,gBAAgB;IAChB,iB/B8pBoD;EHigHxD;AACF;;AkCtpIA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;AlCypIxB;;AkC3pIA;EAOI,mB/B6oBsD;AH2gH1D;;Ac/wII;EoBgHJ;IAWI,uBAAmB;IAAnB,mBAAmB;ElCypIrB;EkCpqIF;IAgBM,gBAAY;IAAZ,YAAY;IACZ,gBAAgB;ElCupIpB;EkCxqIF;IAoBQ,cAAc;IACd,cAAc;ElCupIpB;EkC5qIF;IxBvJI,0BwBkLoC;IxBjLpC,6BwBiLoC;ElCqpItC;EkChrIF;;IAgCY,0BAA0B;ElCopIpC;EkCprIF;;IAqCY,6BAA6B;ElCmpIvC;EkCxrIF;IxBzII,yBwBmLmC;IxBlLnC,4BwBkLmC;ElCkpIrC;EkC5rIF;;IA+CY,yBAAyB;ElCipInC;EkChsIF;;IAoDY,4BAA4B;ElCgpItC;AACF;;AkCpoIA;EAEI,sB/BokBsC;AHkkH1C;;AczzII;EoBiLJ;IAMI,uB/BglBiC;I+BhlBjC,oB/BglBiC;I+BhlBjC,e/BglBiC;I+B/kBjC,2B/BglBuC;I+BhlBvC,wB/BglBuC;I+BhlBvC,mB/BglBuC;I+B/kBvC,UAAU;IACV,SAAS;ElCuoIX;EkChpIF;IAYM,qBAAqB;IACrB,WAAW;ElCuoIf;AACF;;AkC9nIA;EAEI,gBAAgB;AlCgoIpB;;AkCloIA;ExB/PI,gBwBqQ4B;AlCgoIhC;;AkCtoIA;EAUQ,gBAAgB;ExBzQpB,gBwB0Q4B;AlCgoIhC;;AkC3oIA;EAgBM,gBAAgB;ExBxPlB,6BwByPiC;ExBxPjC,4BwBwPiC;AlCgoIrC;;AkCjpIA;ExBtPI,yBwB2Q8B;ExB1Q9B,0BwB0Q8B;AlCioIlC;;AkCtpIA;EAyBM,mB/BtD2B;AHurIjC;;AmC95IA;EACE,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,qBhC2gCsC;EgC1gCtC,mBhC6gCsC;EgC5gCtC,gBAAgB;EAChB,yBhCGgB;EOJd,sBPqOgC;AH8rIpC;;AmC95IA;EAGI,oBhCkgCqC;AH65GzC;;AmCl6IA;EAMM,qBAAqB;EACrB,qBhC8/BmC;EgC7/BnC,chCLY;EgCMZ,YhCmgCuC;AH65G7C;;AmCz6IA;EAoBI,0BAA0B;AnCy5I9B;;AmC76IA;EAwBI,qBAAqB;AnCy5IzB;;AmCj7IA;EA4BI,chCzBc;AHk7IlB;;AoC/7IA;EACE,oBAAa;EAAb,aAAa;E7BGb,eAAe;EACf,gBAAgB;EGAd,sBPqOgC;AH4tIpC;;AoCh8IA;EACE,kBAAkB;EAClB,cAAc;EACd,uBjCqwBwC;EiCpwBxC,iBjC6N+B;EiC5N/B,iBjCwwBsC;EiCvwBtC,cjCwBe;EiCvBf,sBjCNa;EiCOb,yBjCJgB;AHu8IlB;;AoC38IA;EAWI,UAAU;EACV,cjC2J8D;EiC1J9D,qBAAqB;EACrB,yBjCXc;EiCYd,qBjCXc;AH+8IlB;;AoCn9IA;EAmBI,UAAU;EACV,UjCiwBiC;EiChwBjC,gDjCSa;AH27IjB;;AoCh8IA;EAGM,cAAc;E1BChB,+BPuMgC;EOtMhC,kCPsMgC;AH2vIpC;;AoCt8IA;E1BVI,gCPqNgC;EOpNhC,mCPoNgC;AHgwIpC;;AoC38IA;EAcI,UAAU;EACV,WjCvCW;EiCwCX,yBjCXa;EiCYb,qBjCZa;AH68IjB;;AoCl9IA;EAqBI,cjCvCc;EiCwCd,oBAAoB;EAEpB,YAAY;EACZ,sBjCjDW;EiCkDX,qBjC/Cc;AH++IlB;;AqCt/IE;EACE,uBlC8wBsC;ECnpBpC,kBAtCY;EiCnFd,gBlC8N6B;AH2xIjC;;AqCp/IM;E3BwBF,8BPwM+B;EOvM/B,iCPuM+B;AHyxInC;;AqCp/IM;E3BKF,+BPsN+B;EOrN/B,kCPqN+B;AH8xInC;;AqCtgJE;EACE,uBlC4wBqC;ECjpBnC,mBAtCY;EiCnFd,gBlC+N6B;AH0yIjC;;AqCpgJM;E3BwBF,8BPyM+B;EOxM/B,iCPwM+B;AHwyInC;;AqCpgJM;E3BKF,+BPuN+B;EOtN/B,kCPsN+B;AH6yInC;;AsCphJA;EACE,qBAAqB;EACrB,qBnC24BsC;EC10BpC,cAAW;EkC/Db,gBnCmR+B;EmClR/B,cAAc;EACd,kBAAkB;EAClB,mBAAmB;EACnB,wBAAwB;E5BRtB,sBPqOgC;EiBpO9B,qIjBqb6I;AH2mInJ;;AoB3hJI;EkBNJ;IlBOM,gBAAgB;EpB+hJpB;AACF;;AK5hJE;EiCGI,qBAAqB;AtC6hJ3B;;AsC3iJA;EAoBI,aAAa;AtC2hJjB;;AsCthJA;EACE,kBAAkB;EAClB,SAAS;AtCyhJX;;AsClhJA;EACE,oBnCg3BsC;EmC/2BtC,mBnC+2BsC;EOn5BpC,oBPs5BqC;AHoqHzC;;AsC7gJE;ECjDA,WpCMa;EoCLb,yBpCkCe;AHgiJjB;;AKpjJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCkkJxC;;AuCrkJU;EAQJ,UAAU;EACV,+CpCuBW;AH0iJjB;;AsC5hJE;ECjDA,WpCMa;EoCLb,yBpCWgB;AHskJlB;;AKnkJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCilJxC;;AuCplJU;EAQJ,UAAU;EACV,iDpCAY;AHglJlB;;AsC3iJE;ECjDA,WpCMa;EoCLb,yBpCyCe;AHujJjB;;AKllJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvCgmJxC;;AuCnmJU;EAQJ,UAAU;EACV,+CpC8BW;AHikJjB;;AsC1jJE;ECjDA,WpCMa;EoCLb,yBpC2Ce;AHokJjB;;AKjmJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC+mJxC;;AuClnJU;EAQJ,UAAU;EACV,gDpCgCW;AH8kJjB;;AsCzkJE;ECjDA,cpCegB;EoCdhB,yBpCwCe;AHslJjB;;AKhnJE;EkCVI,cpCUY;EoCTZ,yBAAkC;AvC8nJxC;;AuCjoJU;EAQJ,UAAU;EACV,+CpC6BW;AHgmJjB;;AsCxlJE;ECjDA,WpCMa;EoCLb,yBpCsCe;AHumJjB;;AK/nJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC6oJxC;;AuChpJU;EAQJ,UAAU;EACV,+CpC2BW;AHinJjB;;AsCvmJE;ECjDA,cpCegB;EoCdhB,yBpCMgB;AHspJlB;;AK9oJE;EkCVI,cpCUY;EoCTZ,yBAAkC;AvC4pJxC;;AuC/pJU;EAQJ,UAAU;EACV,iDpCLY;AHgqJlB;;AsCtnJE;ECjDA,WpCMa;EoCLb,yBpCagB;AH8pJlB;;AK7pJE;EkCVI,WpCCS;EoCAT,yBAAkC;AvC2qJxC;;AuC9qJU;EAQJ,UAAU;EACV,8CpCEY;AHwqJlB;;AwCvrJA;EACE,kBAAoD;EACpD,mBrC0yBsC;EqCxyBtC,yBrCKgB;EOJd,qBPsO+B;AHm9InC;;AcloJI;E0B5DJ;IAQI,kBrCoyBoC;EHu5HtC;AACF;;AwCxrJA;EACE,gBAAgB;EAChB,eAAe;E9BTb,gB8BUsB;AxC2rJ1B;;AyCtsJA;EACE,kBAAkB;EAClB,wBtCm8ByC;EsCl8BzC,mBtCm8BsC;EsCl8BtC,6BAA6C;E/BH3C,sBPqOgC;AHw+IpC;;AyCrsJA;EAEE,cAAc;AzCusJhB;;AyCnsJA;EACE,gBtCwQ+B;AH87IjC;;AyC9rJA;EACE,mBAAsD;AzCisJxD;;AyClsJA;EAKI,kBAAkB;EAClB,MAAM;EACN,QAAQ;EACR,wBtCq6BuC;EsCp6BvC,cAAc;AzCisJlB;;AyCvrJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBwpJlE;;A0CvuJE;EACE,yBAAqC;A1C0uJzC;;A0CvuJE;EACE,cAA0B;A1C0uJ9B;;AyCrsJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBsqJlE;;A0CrvJE;EACE,yBAAqC;A1CwvJzC;;A0CrvJE;EACE,cAA0B;A1CwvJ9B;;AyCntJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBorJlE;;A0CnwJE;EACE,yBAAqC;A1CswJzC;;A0CnwJE;EACE,cAA0B;A1CswJ9B;;AyCjuJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBksJlE;;A0CjxJE;EACE,yBAAqC;A1CoxJzC;;A0CjxJE;EACE,cAA0B;A1CoxJ9B;;AyC/uJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlBgtJlE;;A0C/xJE;EACE,yBAAqC;A1CkyJzC;;A0C/xJE;EACE,cAA0B;A1CkyJ9B;;AyC7vJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB8tJlE;;A0C7yJE;EACE,yBAAqC;A1CgzJzC;;A0C7yJE;EACE,cAA0B;A1CgzJ9B;;AyC3wJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB4uJlE;;A0C3zJE;EACE,yBAAqC;A1C8zJzC;;A0C3zJE;EACE,cAA0B;A1C8zJ9B;;AyCzxJE;EC9CA,cxBmFgE;EI9E9D,yBJ8E8D;EwBjFhE,qBxBiFgE;AlB0vJlE;;A0Cz0JE;EACE,yBAAqC;A1C40JzC;;A0Cz0JE;EACE,cAA0B;A1C40J9B;;A2Cp1JE;EACE;IAAO,2BAAuC;E3Cw1JhD;E2Cv1JE;IAAK,wBAAwB;E3C01J/B;AACF;;A2C71JE;EACE;IAAO,2BAAuC;E3Cw1JhD;E2Cv1JE;IAAK,wBAAwB;E3C01J/B;AACF;;A2Cv1JA;EACE,oBAAa;EAAb,aAAa;EACb,YxC48BsC;EwC38BtC,gBAAgB;EvCoHZ,kBAtCY;EuC5EhB,yBxCJgB;EOJd,sBPqOgC;AH8nJpC;;A2Ct1JA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EACtB,qBAAuB;EAAvB,uBAAuB;EACvB,WxCfa;EwCgBb,kBAAkB;EAClB,mBAAmB;EACnB,yBxCWe;EiB9BX,2BjBw9B4C;AHq5HlD;;AoBx2JI;EuBOJ;IvBNM,gBAAgB;EpB42JpB;AACF;;A2C51JA;ErBcE,qMAA6I;EqBZ7I,0BxCu7BsC;AHw6HxC;;A2C31JE;EACE,0DxCy7BkD;EwCz7BlD,kDxCy7BkD;AHq6HtD;;A2C51JI;EAHF;IAII,uBAAe;IAAf,eAAe;E3Cg2JnB;AACF;;A4Cx4JA;EACE,oBAAa;EAAb,aAAa;EACb,qBAAuB;EAAvB,uBAAuB;A5C24JzB;;A4Cx4JA;EACE,WAAO;EAAP,OAAO;A5C24JT;;A6C74JA;EACE,oBAAa;EAAb,aAAa;EACb,0BAAsB;EAAtB,sBAAsB;EAGtB,eAAe;EACf,gBAAgB;A7C84JlB;;A6Cr4JA;EACE,WAAW;EACX,c1CPgB;E0CQhB,mBAAmB;A7Cw4JrB;;AK94JE;EwCUE,UAAU;EACV,c1Cbc;E0Ccd,qBAAqB;EACrB,yB1CrBc;AH65JlB;;A6Cl5JA;EAcI,c1CjBc;E0CkBd,yB1CzBc;AHi6JlB;;A6C/3JA;EACE,kBAAkB;EAClB,cAAc;EACd,wB1C47ByC;E0C17BzC,mB1CuL+B;E0CrL/B,sB1C3Ca;E0C4Cb,sC1ClCa;AHk6Jf;;A6Cx4JA;EnC7BI,+BP4NgC;EO3NhC,gCP2NgC;AH8sJpC;;A6C74JA;EAeI,gBAAgB;EnC9BhB,mCP8MgC;EO7MhC,kCP6MgC;AHotJpC;;A6Cn5JA;EAqBI,c1CnDc;E0CoDd,oBAAoB;EACpB,sB1C3DW;AH67Jf;;A6Cz5JA;EA4BI,UAAU;EACV,W1CjEW;E0CkEX,yB1CrCa;E0CsCb,qB1CtCa;AHu6JjB;;A6Cp3JI;EACE,uBAAmB;EAAnB,mBAAmB;A7Cu3JzB;;A6Cx3JI;EAII,kB1C4IyB;E0C3IzB,gBAAgB;A7Cw3JxB;;A6C73JI;EnCpDA,+BPuMgC;EOtMhC,kCPsMgC;EO1LhC,0BmCgDwC;A7C03J5C;;A6Cn4JI;EAaM,eAAe;EnC/ErB,gCPqNgC;EOpNhC,mCPoNgC;EO9KhC,4BmC0C0C;A7C23J9C;;Acr6JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7C84JvB;E6C/4JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7C84JtB;E6Cn5JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7C+4J1C;E6Cx5JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7C+4J5C;AACF;;Ac17JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7Cm6JvB;E6Cp6JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7Cm6JtB;E6Cx6JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7Co6J1C;E6C76JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7Co6J5C;AACF;;Ac/8JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7Cw7JvB;E6Cz7JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7Cw7JtB;E6C77JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7Cy7J1C;E6Cl8JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7Cy7J5C;AACF;;Acp+JI;E+B2BA;IACE,uBAAmB;IAAnB,mBAAmB;E7C68JvB;E6C98JE;IAII,kB1C4IyB;I0C3IzB,gBAAgB;E7C68JtB;E6Cl9JE;InCpDA,+BPuMgC;IOtMhC,kCPsMgC;IO1LhC,0BmCgDwC;E7C88J1C;E6Cv9JE;IAaM,eAAe;InC/ErB,gCPqNgC;IOpNhC,mCPoNgC;IO9KhC,4BmC0C0C;E7C88J5C;AACF;;A6Cl8JA;EAEI,eAAe;EACf,cAAc;EnCjHd,gBmCkHwB;A7Co8J5B;;A6Cx8JA;EAOM,mB1C6G2B;AHw1JjC;;A6C58JA;EAaM,aAAa;A7Cm8JnB;;A6Ch9JA;EAmBM,gBAAgB;EAChB,gBAAgB;A7Ci8JtB;;A8CrkKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBy/JlE;;AK7jKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwkKjD;;A8C/kKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBogKlE;;A8CrlKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBygKlE;;AK7kKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwlKjD;;A8C/lKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBohKlE;;A8CrmKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByhKlE;;AK7lKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwmKjD;;A8C/mKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBoiKlE;;A8CrnKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByiKlE;;AK7mKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwnKjD;;A8C/nKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBojKlE;;A8CroKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlByjKlE;;AK7nKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwoKjD;;A8C/oKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBokKlE;;A8CrpKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBykKlE;;AK7oKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwpKjD;;A8C/pKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBolKlE;;A8CrqKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBylKlE;;AK7pKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwqKjD;;A8C/qKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBomKlE;;A8CrrKE;EACE,c5BgF8D;E4B/E9D,yB5B+E8D;AlBymKlE;;AK7qKE;EyCPM,c5B2E0D;E4B1E1D,yBAAyC;A9CwrKjD;;A8C/rKE;EAWM,W3CPO;E2CQP,yB5BqE0D;E4BpE1D,qB5BoE0D;AlBonKlE;;A+CxsKA;EACE,YAAY;E3C8HR,iBAtCY;E2CtFhB,gB5CyR+B;E4CxR/B,cAAc;EACd,W5CYa;E4CXb,yB5CCa;E4CAb,WAAW;A/C2sKb;;AKtsKE;E0CDE,W5CMW;E4CLX,qBAAqB;A/C2sKzB;;AKvsKE;E0CCI,YAAY;A/C0sKlB;;A+C/rKA;EACE,UAAU;EACV,6BAA6B;EAC7B,SAAS;EACT,wBAAgB;EAAhB,qBAAgB;EAAhB,gBAAgB;A/CksKlB;;A+C5rKA;EACE,oBAAoB;A/C+rKtB;;AgDtuKA;EACE,gB7C43BuC;E6C33BvC,gBAAgB;E5C6HZ,mBAtCY;E4CpFhB,2C7CEa;E6CDb,4BAA4B;EAC5B,oC7C63BmD;E6C53BnD,gD7CSa;E6CRb,mCAA2B;EAA3B,2BAA2B;EAC3B,UAAU;EtCLR,sBPg4BsC;AH82I1C;;AgDnvKA;EAcI,sB7Cg3BsC;AHy3I1C;;AgDvvKA;EAkBI,UAAU;AhDyuKd;;AgD3vKA;EAsBI,cAAc;EACd,UAAU;AhDyuKd;;AgDhwKA;EA2BI,aAAa;AhDyuKjB;;AgDruKA;EACE,oBAAa;EAAb,aAAa;EACb,sBAAmB;EAAnB,mBAAmB;EACnB,wB7C41BwC;E6C31BxC,c7CtBgB;E6CuBhB,2C7C7Ba;E6C8Bb,4BAA4B;EAC5B,4C7Co2BoD;AHo4ItD;;AgDruKA;EACE,gB7Co1BwC;AHo5I1C;;AiD5wKA;EAEE,gBAAgB;AjD8wKlB;;AiDhxKA;EAKI,kBAAkB;EAClB,gBAAgB;AjD+wKpB;;AiD1wKA;EACE,eAAe;EACf,MAAM;EACN,OAAO;EACP,a9CopBsC;E8CnpBtC,aAAa;EACb,WAAW;EACX,YAAY;EACZ,gBAAgB;EAGhB,UAAU;AjD2wKZ;;AiDpwKA;EACE,kBAAkB;EAClB,WAAW;EACX,c9C63BuC;E8C33BvC,oBAAoB;AjDswKtB;;AiDnwKE;E7BrCI,2CjB27BoD;EiB37BpD,mCjB27BoD;EiB37BpD,oEjB27BoD;E8Cp5BtD,sC9Ck5BmD;E8Cl5BnD,8B9Ck5BmD;AHo3IvD;;AoBxyKI;E6BgCF;I7B/BI,gBAAgB;EpB4yKpB;AACF;;AiD1wKE;EACE,uB9Cg5BoC;E8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hLf;;AkD3+KA;EACE,iBAAgC;AlD8+KlC;;AkD/+KA;EAII,MAAM;AlD++KV;;AkDn/KA;EAOM,SAAS;EACT,6B/CgxBmC;E+C/wBnC,yB/CrDS;AHqiLf;;AkD3+KA;EACE,iB/CywBuC;AHquJzC;;AkD/+KA;EAII,QAAQ;EACR,a/CqwBqC;E+CpwBrC,c/CmwBqC;AH4uJzC;;AkDr/KA;EASM,OAAO;EACP,oC/CgwBmC;E+C/vBnC,uB/CrES;AHqjLf;;AkD39KA;EACE,gB/C+tBuC;E+C9tBvC,uB/CouBuC;E+CnuBvC,W/CvGa;E+CwGb,kBAAkB;EAClB,sB/C/Fa;EOZX,sBPqOgC;AHq2KpC;;AoD/kLA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,ajDsqBsC;EiDrqBtC,cAAc;EACd,gBjD+1BuC;EgDp2BvC,kMhD+QiN;EgD7QjN,kBAAkB;EAClB,gBhDuR+B;EgDtR/B,gBhD2R+B;EgD1R/B,gBAAgB;EAChB,iBAAiB;EACjB,qBAAqB;EACrB,iBAAiB;EACjB,oBAAoB;EACpB,sBAAsB;EACtB,kBAAkB;EAClB,oBAAoB;EACpB,mBAAmB;EACnB,gBAAgB;E/CgHZ,mBAtCY;EgD7EhB,qBAAqB;EACrB,sBjDNa;EiDOb,4BAA4B;EAC5B,oCjDEa;EOZX,qBPsO+B;AHi4KnC;;AoD5mLA;EAoBI,kBAAkB;EAClB,cAAc;EACd,WjD81BoC;EiD71BpC,cjD81BqC;EiD71BrC,gBjDmN+B;AHy4KnC;;AoDpnLA;EA4BM,kBAAkB;EAClB,cAAc;EACd,WAAW;EACX,yBAAyB;EACzB,mBAAmB;ApD4lLzB;;AoDvlLA;EACE,qBjD+0BuC;AH2wJzC;;AoD3lLA;EAII,iCAAwE;ApD2lL5E;;AoD/lLA;EAOM,SAAS;EACT,6BAAgE;EAChE,qCjD00BiE;AHkxJvE;;AoDrmLA;EAaM,WjDqL2B;EiDpL3B,6BAAgE;EAChE,sBjD7CS;AHyoLf;;AoDvlLA;EACE,mBjD2zBuC;AH+xJzC;;AoD3lLA;EAII,+BAAsE;EACtE,ajDuzBqC;EiDtzBrC,YjDqzBoC;EiDpzBpC,gBAA2B;ApD2lL/B;;AoDlmLA;EAUM,OAAO;EACP,oCAA2F;EAC3F,uCjDmzBiE;AHyyJvE;;AoDxmLA;EAgBM,SjD8J2B;EiD7J3B,oCAA2F;EAC3F,wBjDpES;AHgqLf;;AoDvlLA;EACE,kBjDoyBuC;AHszJzC;;AoD3lLA;EAII,8BAAqE;ApD2lLzE;;AoD/lLA;EAOM,MAAM;EACN,oCAA2F;EAC3F,wCjD+xBiE;AH6zJvE;;AoDrmLA;EAaM,QjD0I2B;EiDzI3B,oCAA2F;EAC3F,yBjDxFS;AHorLf;;AoD3mLA;EAqBI,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,cAAc;EACd,WjD2wBoC;EiD1wBpC,oBAAsC;EACtC,WAAW;EACX,gCjD+vBuD;AH21J3D;;AoDtlLA;EACE,oBjDowBuC;AHq1JzC;;AoD1lLA;EAII,gCAAuE;EACvE,ajDgwBqC;EiD/vBrC,YjD8vBoC;EiD7vBpC,gBAA2B;ApD0lL/B;;AoDjmLA;EAUM,QAAQ;EACR,oCjD0vBmC;EiDzvBnC,sCjD4vBiE;AH+1JvE;;AoDvmLA;EAgBM,UjDuG2B;EiDtG3B,oCjDovBmC;EiDnvBnC,uBjD3HS;AHstLf;;AoDrkLA;EACE,uBjDqtBwC;EiDptBxC,gBAAgB;EhD3BZ,eAtCY;EgDoEhB,yBjD8sByD;EiD7sBzD,gCAAyE;E1ChJvE,0C0CiJyE;E1ChJzE,2C0CgJyE;ApDwkL7E;;AoD/kLA;EAWI,aAAa;ApDwkLjB;;AoDpkLA;EACE,uBjDssBwC;EiDrsBxC,cjDzJgB;AHguLlB;;AqDnuLA;EACE,kBAAkB;ArDsuLpB;;AqDnuLA;EACE,uBAAmB;EAAnB,mBAAmB;ArDsuLrB;;AqDnuLA;EACE,kBAAkB;EAClB,WAAW;EACX,gBAAgB;ArDsuLlB;;AsD7vLE;EACE,cAAc;EACd,WAAW;EACX,WAAW;AtDgwLf;;AqDxuLA;EACE,kBAAkB;EAClB,aAAa;EACb,WAAW;EACX,WAAW;EACX,mBAAmB;EACnB,mCAA2B;EAA3B,2BAA2B;EjC5BvB,8CjB6iCkF;EiB7iClF,sCjB6iCkF;EiB7iClF,0EjB6iCkF;AH2tJxF;;AoBnwLI;EiCiBJ;IjChBM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E,oCAAmC;AzD4/LvC;;AKl/LE;;;EoDLI,oCAAgD;AzD6/LtD;;AyDngME;EACE,oCAAmC;AzDsgMvC;;AK5/LE;;;EoDLI,oCAAgD;AzDugMtD;;AyD7gME;EACE,oCAAmC;AzDghMvC;;AKtgME;;;EoDLI,oCAAgD;AzDihMtD;;AyDvhME;EACE,oCAAmC;AzD0hMvC;;AKhhME;;;EoDLI,oCAAgD;AzD2hMtD;;AyDjiME;EACE,oCAAmC;AzDoiMvC;;AK1hME;;;EoDLI,oCAAgD;AzDqiMtD;;AyD3iME;EACE,oCAAmC;AzD8iMvC;;AKpiME;;;EoDLI,oCAAgD;AzD+iMtD;;AyDrjME;EACE,oCAAmC;AzDwjMvC;;AK9iME;;;EoDLI,oCAAgD;AzDyjMtD;;A0DxjMA;EACE,iCAAmC;A1D2jMrC;;A0DxjMA;EACE,wCAAwC;A1D2jM1C;;A2DtkMA;EAAkB,oCAAoD;A3D0kMtE;;A2DzkMA;EAAkB,wCAAwD;A3D6kM1E;;A2D5kMA;EAAkB,0CAA0D;A3DglM5E;;A2D/kMA;EAAkB,2CAA2D;A3DmlM7E;;A2DllMA;EAAkB,yCAAyD;A3DslM3E;;A2DplMA;EAAmB,oBAAoB;A3DwlMvC;;A2DvlMA;EAAmB,wBAAwB;A3D2lM3C;;A2D1lMA;EAAmB,0BAA0B;A3D8lM7C;;A2D7lMA;EAAmB,2BAA2B;A3DimM9C;;A2DhmMA;EAAmB,yBAAyB;A3DomM5C;;A2DjmME;EACE,gCAA+B;A3DomMnC;;A2DrmME;EACE,gCAA+B;A3DwmMnC;;A2DzmME;EACE,gCAA+B;A3D4mMnC;;A2D7mME;EACE,gCAA+B;A3DgnMnC;;A2DjnME;EACE,gCAA+B;A3DonMnC;;A2DrnME;EACE,gCAA+B;A3DwnMnC;;A2DznME;EACE,gCAA+B;A3D4nMnC;;A2D7nME;EACE,gCAA+B;A3DgoMnC;;A2D5nMA;EACE,6BAA+B;A3D+nMjC;;A2DxnMA;EACE,gCAA2C;A3D2nM7C;;A2DxnMA;EACE,iCAAwC;A3D2nM1C;;A2DxnMA;EACE,0CAAiD;EACjD,2CAAkD;A3D2nMpD;;A2DxnMA;EACE,2CAAkD;EAClD,8CAAqD;A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tOhD;;AuEjuOQ;EAAgC,yBAA4B;AvEquOpE;;AuEpuOQ;;EAEE,6BAAoC;AvEuuO9C;;AuEruOQ;;EAEE,+BAAwC;AvEwuOlD;;AuEtuOQ;;EAEE,gCAA0C;AvEyuOpD;;AuEvuOQ;;EAEE,8BAAsC;AvE0uOhD;;AuEzvOQ;EAAgC,uBAA4B;AvE6vOpE;;AuE5vOQ;;EAEE,2BAAoC;AvE+vO9C;;AuE7vOQ;;EAEE,6BAAwC;AvEgwOlD;;AuE9vOQ;;EAEE,8BAA0C;AvEiwOpD;;AuE/vOQ;;EAEE,4BAAsC;AvEkwOhD;;AuEjxOQ;EAAgC,yBAA4B;AvEqxOpE;;AuEpxOQ;;EAEE,6BAAoC;AvEuxO9C;;AuErxOQ;;EAEE,+BAAwC;AvEwxOlD;;AuEtxOQ;;EAEE,gCAA0C;AvEyxOpD;;AuEvxOQ;;EAEE,8BAAsC;AvE0xOhD;;AuEzyOQ;EAAgC,uBAA4B;AvE6yOpE;;AuE5yOQ;;EAEE,2BAAoC;AvE+yO9C;;AuE7yOQ;;EAEE,6BAAwC;AvEgzOlD;;AuE9yOQ;;EAEE,8BAA0C;AvEizOpD;;AuE/yOQ;;EAEE,4BAAsC;AvEkzOhD;;AuEj0OQ;EAAgC,qBAA4B;AvEq0OpE;;AuEp0OQ;;EAEE,yBAAoC;AvEu0O9C;;AuEr0OQ;;EAEE,2BAAwC;AvEw0OlD;;AuEt0OQ;;EAEE,4BAA0C;AvEy0OpD;;AuEv0OQ;;EAEE,0BAAsC;AvE00OhD;;AuEz1OQ;EAAgC,2BAA4B;AvE61OpE;;AuE51OQ;;EAEE,+BAAoC;AvE+1O9C;;AuE71OQ;;EAEE,iCAAwC;AvEg2OlD;;AuE91OQ;;EAEE,kCAA0C;AvEi2OpD;;AuE/1OQ;;EAEE,gCAAsC;AvEk2OhD;;AuEj3OQ;EAAgC,0BAA4B;AvEq3OpE;;AuEp3OQ;;EAEE,8BAAoC;AvEu3O9C;;AuEr3OQ;;EAEE,gCAAwC;AvEw3OlD;;AuEt3OQ;;EAEE,iCAA0C;AvEy3OpD;;AuEv3OQ;;EAEE,+BAAsC;AvE03OhD;;AuEz4OQ;EAAgC,wBAA4B;AvE64OpE;;AuE54OQ;;EAEE,4BAAoC;AvE+4O9C;;AuE74OQ;;EAEE,8BAAwC;AvEg5OlD;;AuE94OQ;;EAEE,+BAA0C;AvEi5OpD;;AuE/4OQ;;EAEE,6BAAsC;AvEk5OhD;;AuEj6OQ;EAAgC,0BAA4B;AvEq6OpE;;AuEp6OQ;;EAEE,8BAAoC;AvEu6O9C;;AuEr6OQ;;EAEE,gCAAwC;AvEw6OlD;;AuEt6OQ;;EAEE,iCAA0C;AvEy6OpD;;AuEv6OQ;;EAEE,+BAAsC;AvE06OhD;;AuEz7OQ;EAAgC,wBAA4B;AvE67OpE;;AuE57OQ;;EAEE,4BAAoC;AvE+7O9C;;AuE77OQ;;EAEE,8BAAwC;AvEg8OlD;;AuE97OQ;;EAEE,+BAA0C;AvEi8OpD;;AuE/7OQ;;EAEE,6BAAsC;AvEk8OhD;;AuE17OQ;EAAwB,2BAA2B;AvE87O3D;;AuE77OQ;;EAEE,+BAA+B;AvEg8OzC;;AuE97OQ;;EAEE,iCAAiC;AvEi8O3C;;AuE/7OQ;;EAEE,kCAAkC;AvEk8O5C;;AuEh8OQ;;EAEE,gCAAgC;AvEm8O1C;;AuEl9OQ;EAAwB,0BAA2B;AvEs9O3D;;AuEr9OQ;;EAEE,8BAA+B;AvEw9OzC;;AuEt9OQ;;EAEE,gCAAiC;AvEy9O3C;;AuEv9OQ;;EAEE,iCAAkC;AvE09O5C;;AuEx9OQ;;EAEE,+BAAgC;AvE29O1C;;AuE1+OQ;EAAwB,wBAA2B;AvE8+O3D;;AuE7+OQ;;EAEE,4BAA+B;AvEg/OzC;;AuE9+OQ;;EAEE,8BAAiC;AvEi/O3C;;AuE/+OQ;;EAEE,+BAAkC;AvEk/O5C;;AuEh/OQ;;EAEE,6BAAgC;AvEm/O1C;;AuElgPQ;EAAwB,0BAA2B;AvEsgP3D;;AuErgPQ;;EAEE,8BAA+B;AvEwgPzC;;AuEtgPQ;;EAEE,gCAAiC;AvEygP3C;;AuEvgPQ;;EAEE,iCAAkC;AvE0gP5C;;AuExgPQ;;EAEE,+BAAgC;AvE2gP1C;;AuE1hPQ;EAAwB,wBAA2B;AvE8hP3D;;AuE7hPQ;;EAEE,4BAA+B;AvEgiPzC;;AuE9hPQ;;EAEE,8BAAiC;AvEiiP3C;;AuE/hPQ;;EAEE,+BAAkC;AvEkiP5C;;AuEhiPQ;;EAEE,6BAAgC;AvEmiP1C;;AuE7hPI;EAAmB,uBAAuB;AvEiiP9C;;AuEhiPI;;EAEE,2BAA2B;AvEmiPjC;;AuEjiPI;;EAEE,6BAA6B;AvEoiPnC;;AuEliPI;;EAEE,8BAA8B;AvEqiPpC;;AuEniPI;;EAEE,4BAA4B;AvEsiPlC;;Ac/iPI;EyDlDI;IAAgC,oBAA4B;EvEsmPlE;EuErmPM;;IAEE,wBAAoC;EvEumP5C;EuErmPM;;IAEE,0BAAwC;EvEumPhD;EuErmPM;;IAEE,2BAA0C;EvEumPlD;EuErmPM;;IAEE,yBAAsC;EvEumP9C;EuEtnPM;IAAgC,0BAA4B;EvEynPlE;EuExnPM;;IAEE,8BAAoC;EvE0nP5C;EuExnPM;;IAEE,gCAAwC;EvE0nPhD;EuExnPM;;IAEE,iCAA0C;EvE0nPlD;EuExnPM;;IAEE,+BAAsC;EvE0nP9C;EuEzoPM;IAAgC,yBAA4B;EvE4oPlE;EuE3oPM;;IAEE,6BAAoC;EvE6oP5C;EuE3oPM;;IAEE,+BAAwC;EvE6oPhD;EuE3oPM;;IAEE,gCAA0C;EvE6oPlD;EuE3oPM;;IAEE,8BAAsC;EvE6oP9C;EuE5pPM;IAAgC,uBAA4B;EvE+pPlE;EuE9pPM;;IAEE,2BAAoC;EvEgqP5C;EuE9pPM;;IAEE,6BAAwC;EvEgqPhD;EuE9pPM;;IAEE,8BAA0C;EvEgqPlD;EuE9pPM;;IAEE,4BAAsC;EvEgqP9C;EuE/qPM;IAAgC,yBAA4B;EvEkrPlE;EuEjrPM;;IAEE,6BAAoC;EvEmrP5C;EuEjrPM;;IAEE,+BAAwC;EvEmrPhD;EuEjrPM;;IAEE,gCAA0C;EvEmrPlD;EuEjrPM;;IAEE,8BAAsC;EvEmrP9C;EuElsPM;IAAgC,uBAA4B;EvEqsPlE;EuEpsPM;;IAEE,2BAAoC;EvEssP5C;EuEpsPM;;IAEE,6BAAwC;EvEssPhD;EuEpsPM;;IAEE,8BAA0C;EvEssPlD;EuEpsPM;;IAEE,4BAAsC;EvEssP9C;EuErtPM;IAAgC,qBAA4B;EvEwtPlE;EuEvtPM;;IAEE,yBAAoC;EvEytP5C;EuEvtPM;;IAEE,2BAAwC;EvEytPhD;EuEvtPM;;IAEE,4BAA0C;EvEytPlD;EuEvtPM;;IAEE,0BAAsC;EvEytP9C;EuExuPM;IAAgC,2BAA4B;EvE2uPlE;EuE1uPM;;IAEE,+BAAoC;EvE4uP5C;EuE1uPM;;IAEE,iCAAwC;EvE4uPhD;EuE1uPM;;IAEE,kCAA0C;EvE4uPlD;EuE1uPM;;IAEE,gCAAsC;EvE4uP9C;EuE3vPM;IAAgC,0BAA4B;EvE8vPlE;EuE7vPM;;IAEE,8BAAoC;EvE+vP5C;EuE7vPM;;IAEE,gCAAwC;EvE+vPhD;EuE7vPM;;IAEE,iCAA0C;EvE+vPlD;EuE7vPM;;IAEE,+BAAsC;EvE+vP9C;EuE9wPM;IAAgC,wBAA4B;EvEixPlE;EuEhxPM;;IAEE,4BAAoC;EvEkxP5C;EuEhxPM;;IAEE,8BAAwC;EvEkxPhD;EuEhxPM;;IAEE,+BAA0C;EvEkxPlD;EuEhxPM;;IAEE,6BAAsC;EvEkxP9C;EuEjyPM;IAAgC,0BAA4B;EvEoyPlE;EuEnyPM;;IAEE,8BAAoC;EvEqyP5C;EuEnyPM;;IAEE,gCAAwC;EvEqyPhD;EuEnyPM;;IAEE,iCAA0C;EvEqyPlD;EuEnyPM;;IAEE,+BAAsC;EvEqyP9C;EuEpzPM;IAAgC,wBAA4B;EvEuzPlE;EuEtzPM;;IAEE,4BAAoC;EvEwzP5C;EuEtzPM;;IAEE,8BAAwC;EvEwzPhD;EuEtzPM;;IAEE,+BAA0C;EvEwzPlD;EuEtzPM;;IAEE,6BAAsC;EvEwzP9C;EuEhzPM;IAAwB,2BAA2B;EvEmzPzD;EuElzPM;;IAEE,+BAA+B;EvEozPvC;EuElzPM;;IAEE,iCAAiC;EvEozPzC;EuElzPM;;IAEE,kCAAkC;EvEozP1C;EuElzPM;;IAEE,gCAAgC;EvEozPxC;EuEn0PM;IAAwB,0BAA2B;EvEs0PzD;EuEr0PM;;IAEE,8BAA+B;EvEu0PvC;EuEr0PM;;IAEE,gCAAiC;EvEu0PzC;EuEr0PM;;IAEE,iCAAkC;EvEu0P1C;EuEr0PM;;IAEE,+BAAgC;EvEu0PxC;EuEt1PM;IAAwB,wBAA2B;EvEy1PzD;EuEx1PM;;IAEE,4BAA+B;EvE01PvC;EuEx1PM;;IAEE,8BAAiC;EvE01PzC;EuEx1PM;;IAEE,+BAAkC;EvE01P1C;EuEx1PM;;IAEE,6BAAgC;EvE01PxC;EuEz2PM;IAAwB,0BAA2B;EvE42PzD;EuE32PM;;IAEE,8BAA+B;EvE62PvC;EuE32PM;;IAEE,gCAAiC;EvE62PzC;EuE32PM;;IAEE,iCAAkC;EvE62P1C;EuE32PM;;IAEE,+BAAgC;EvE62PxC;EuE53PM;IAAwB,wBAA2B;EvE+3PzD;EuE93PM;;IAEE,4BAA+B;EvEg4PvC;EuE93PM;;IAEE,8BAAiC;EvEg4PzC;EuE93PM;;IAEE,+BAAkC;EvEg4P1C;EuE93PM;;IAEE,6BAAgC;EvEg4PxC;EuE13PE;IAAmB,uBAAuB;EvE63P5C;EuE53PE;;IAEE,2BAA2B;EvE83P/B;EuE53PE;;IAEE,6BAA6B;EvE83PjC;EuE53PE;;IAEE,8BAA8B;EvE83PlC;EuE53PE;;IAEE,4BAA4B;EvE83PhC;AACF;;Acx4PI;EyDlDI;IAAgC,oBAA4B;EvE+7PlE;EuE97PM;;IAEE,wBAAoC;EvEg8P5C;EuE97PM;;IAEE,0BAAwC;EvEg8PhD;EuE97PM;;IAEE,2BAA0C;EvEg8PlD;EuE97PM;;IAEE,yBAAsC;EvEg8P9C;EuE/8PM;IAAgC,0BAA4B;EvEk9PlE;EuEj9PM;;IAEE,8BAAoC;EvEm9P5C;EuEj9PM;;IAEE,gCAAwC;EvEm9PhD;EuEj9PM;;IAEE,iCAA0C;EvEm9PlD;EuEj9PM;;IAEE,+BAAsC;EvEm9P9C;EuEl+PM;IAAgC,yBAA4B;EvEq+PlE;EuEp+PM;;IAEE,6BAAoC;EvEs+P5C;EuEp+PM;;IAEE,+BAAwC;EvEs+PhD;EuEp+PM;;IAEE,gCAA0C;EvEs+PlD;EuEp+PM;;IAEE,8BAAsC;EvEs+P9C;EuEr/PM;IAAgC,uBAA4B;EvEw/PlE;EuEv/PM;;IAEE,2BAAoC;EvEy/P5C;EuEv/PM;;IAEE,6BAAwC;EvEy/PhD;EuEv/PM;;IAEE,8BAA0C;EvEy/PlD;EuEv/PM;;IAEE,4BAAsC;EvEy/P9C;EuExgQM;IAAgC,yBAA4B;EvE2gQlE;EuE1gQM;;IAEE,6BAAoC;EvE4gQ5C;EuE1gQM;;IAEE,+BAAwC;EvE4gQhD;EuE1gQM;;IAEE,gCAA0C;EvE4gQlD;EuE1gQM;;IAEE,8BAAsC;EvE4gQ9C;EuE3hQM;IAAgC,uBAA4B;EvE8hQlE;EuE7hQM;;IAEE,2BAAoC;EvE+hQ5C;EuE7hQM;;IAEE,6BAAwC;EvE+hQhD;EuE7hQM;;IAEE,8BAA0C;EvE+hQlD;EuE7hQM;;IAEE,4BAAsC;EvE+hQ9C;EuE9iQM;IAAgC,qBAA4B;EvEijQlE;EuEhjQM;;IAEE,yBAAoC;EvEkjQ5C;EuEhjQM;;IAEE,2BAAwC;EvEkjQhD;EuEhjQM;;IAEE,4BAA0C;EvEkjQlD;EuEhjQM;;IAEE,0BAAsC;EvEkjQ9C;EuEjkQM;IAAgC,2BAA4B;EvEokQlE;EuEnkQM;;IAEE,+BAAoC;EvEqkQ5C;EuEnkQM;;IAEE,iCAAwC;EvEqkQhD;EuEnkQM;;IAEE,kCAA0C;EvEqkQlD;EuEnkQM;;IAEE,gCAAsC;EvEqkQ9C;EuEplQM;IAAgC,0BAA4B;EvEulQlE;EuEtlQM;;IAEE,8BAAoC;EvEwlQ5C;EuEtlQM;;IAEE,gCAAwC;EvEwlQhD;EuEtlQM;;IAEE,iCAA0C;EvEwlQlD;EuEtlQM;;IAEE,+BAAsC;EvEwlQ9C;EuEvmQM;IAAgC,wBAA4B;EvE0mQlE;EuEzmQM;;IAEE,4BAAoC;EvE2mQ5C;EuEzmQM;;IAEE,8BAAwC;EvE2mQhD;EuEzmQM;;IAEE,+BAA0C;EvE2mQlD;EuEzmQM;;IAEE,6BAAsC;EvE2mQ9C;EuE1nQM;IAAgC,0BAA4B;EvE6nQlE;EuE5nQM;;IAEE,8BAAoC;EvE8nQ5C;EuE5nQM;;IAEE,gCAAwC;EvE8nQhD;EuE5nQM;;IAEE,iCAA0C;EvE8nQlD;EuE5nQM;;IAEE,+BAAsC;EvE8nQ9C;EuE7oQM;IAAgC,wBAA4B;EvEgpQlE;EuE/oQM;;IAEE,4BAAoC;EvEipQ5C;EuE/oQM;;IAEE,8BAAwC;EvEipQhD;EuE/oQM;;IAEE,+BAA0C;EvEipQlD;EuE/oQM;;IAEE,6BAAsC;EvEipQ9C;EuEzoQM;IAAwB,2BAA2B;EvE4oQzD;EuE3oQM;;IAEE,+BAA+B;EvE6oQvC;EuE3oQM;;IAEE,iCAAiC;EvE6oQzC;EuE3oQM;;IAEE,kCAAkC;EvE6oQ1C;EuE3oQM;;IAEE,gCAAgC;EvE6oQxC;EuE5pQM;IAAwB,0BAA2B;EvE+pQzD;EuE9pQM;;IAEE,8BAA+B;EvEgqQvC;EuE9pQM;;IAEE,gCAAiC;EvEgqQzC;EuE9pQM;;IAEE,iCAAkC;EvEgqQ1C;EuE9pQM;;IAEE,+BAAgC;EvEgqQxC;EuE/qQM;IAAwB,wBAA2B;EvEkrQzD;EuEjrQM;;IAEE,4BAA+B;EvEmrQvC;EuEjrQM;;IAEE,8BAAiC;EvEmrQzC;EuEjrQM;;IAEE,+BAAkC;EvEmrQ1C;EuEjrQM;;IAEE,6BAAgC;EvEmrQxC;EuElsQM;IAAwB,0BAA2B;EvEqsQzD;EuEpsQM;;IAEE,8BAA+B;EvEssQvC;EuEpsQM;;IAEE,gCAAiC;EvEssQzC;EuEpsQM;;IAEE,iCAAkC;EvEssQ1C;EuEpsQM;;IAEE,+BAAgC;EvEssQxC;EuErtQM;IAAwB,wBAA2B;EvEwtQzD;EuEvtQM;;IAEE,4BAA+B;EvEytQvC;EuEvtQM;;IAEE,8BAAiC;EvEytQzC;EuEvtQM;;IAEE,+BAAkC;EvEytQ1C;EuEvtQM;;IAEE,6BAAgC;EvEytQxC;EuEntQE;IAAmB,uBAAuB;EvEstQ5C;EuErtQE;;IAEE,2BAA2B;EvEutQ/B;EuErtQE;;IAEE,6BAA6B;EvEutQjC;EuErtQE;;IAEE,8BAA8B;EvEutQlC;EuErtQE;;IAEE,4BAA4B;EvEutQhC;AACF;;AcjuQI;EyDlDI;IAAgC,oBAA4B;EvEwxQlE;EuEvxQM;;IAEE,wBAAoC;EvEyxQ5C;EuEvxQM;;IAEE,0BAAwC;EvEyxQhD;EuEvxQM;;IAEE,2BAA0C;EvEyxQlD;EuEvxQM;;IAEE,yBAAsC;EvEyxQ9C;EuExyQM;IAAgC,0BAA4B;EvE2yQlE;EuE1yQM;;IAEE,8BAAoC;EvE4yQ5C;EuE1yQM;;IAEE,gCAAwC;EvE4yQhD;EuE1yQM;;IAEE,iCAA0C;EvE4yQlD;EuE1yQM;;IAEE,+BAAsC;EvE4yQ9C;EuE3zQM;IAAgC,yBAA4B;EvE8zQlE;EuE7zQM;;IAEE,6BAAoC;EvE+zQ5C;EuE7zQM;;IAEE,+BAAwC;EvE+zQhD;EuE7zQM;;IAEE,gCAA0C;EvE+zQlD;EuE7zQM;;IAEE,8BAAsC;EvE+zQ9C;EuE90QM;IAAgC,uBAA4B;EvEi1QlE;EuEh1QM;;IAEE,2BAAoC;EvEk1Q5C;EuEh1QM;;IAEE,6BAAwC;EvEk1QhD;EuEh1QM;;IAEE,8BAA0C;EvEk1QlD;EuEh1QM;;IAEE,4BAAsC;EvEk1Q9C;EuEj2QM;IAAgC,yBAA4B;EvEo2QlE;EuEn2QM;;IAEE,6BAAoC;EvEq2Q5C;EuEn2QM;;IAEE,+BAAwC;EvEq2QhD;EuEn2QM;;IAEE,gCAA0C;EvEq2QlD;EuEn2QM;;IAEE,8BAAsC;EvEq2Q9C;EuEp3QM;IAAgC,uBAA4B;EvEu3QlE;EuEt3QM;;IAEE,2BAAoC;EvEw3Q5C;EuEt3QM;;IAEE,6BAAwC;EvEw3QhD;EuEt3QM;;IAEE,8BAA0C;EvEw3QlD;EuEt3QM;;IAEE,4BAAsC;EvEw3Q9C;EuEv4QM;IAAgC,qBAA4B;EvE04QlE;EuEz4QM;;IAEE,yBAAoC;EvE24Q5C;EuEz4QM;;IAEE,2BAAwC;EvE24QhD;EuEz4QM;;IAEE,4BAA0C;EvE24QlD;EuEz4QM;;IAEE,0BAAsC;EvE24Q9C;EuE15QM;IAAgC,2BAA4B;EvE65QlE;EuE55QM;;IAEE,+BAAoC;EvE85Q5C;EuE55QM;;IAEE,iCAAwC;EvE85QhD;EuE55QM;;IAEE,kCAA0C;EvE85QlD;EuE55QM;;IAEE,gCAAsC;EvE85Q9C;EuE76QM;IAAgC,0BAA4B;EvEg7QlE;EuE/6QM;;IAEE,8BAAoC;EvEi7Q5C;EuE/6QM;;IAEE,gCAAwC;EvEi7QhD;EuE/6QM;;IAEE,iCAA0C;EvEi7QlD;EuE/6QM;;IAEE,+BAAsC;EvEi7Q9C;EuEh8QM;IAAgC,wBAA4B;EvEm8QlE;EuEl8QM;;IAEE,4BAAoC;EvEo8Q5C;EuEl8QM;;IAEE,8BAAwC;EvEo8QhD;EuEl8QM;;IAEE,+BAA0C;EvEo8QlD;EuEl8QM;;IAEE,6BAAsC;EvEo8Q9C;EuEn9QM;IAAgC,0BAA4B;EvEs9QlE;EuEr9QM;;IAEE,8BAAoC;EvEu9Q5C;EuEr9QM;;IAEE,gCAAwC;EvEu9QhD;EuEr9QM;;IAEE,iCAA0C;EvEu9QlD;EuEr9QM;;IAEE,+BAAsC;EvEu9Q9C;EuEt+QM;IAAgC,wBAA4B;EvEy+QlE;EuEx+QM;;IAEE,4BAAoC;EvE0+Q5C;EuEx+QM;;IAEE,8BAAwC;EvE0+QhD;EuEx+QM;;IAEE,+BAA0C;EvE0+QlD;EuEx+QM;;IAEE,6BAAsC;EvE0+Q9C;EuEl+QM;IAAwB,2BAA2B;EvEq+QzD;EuEp+QM;;IAEE,+BAA+B;EvEs+QvC;EuEp+QM;;IAEE,iCAAiC;EvEs+QzC;EuEp+QM;;IAEE,kCAAkC;EvEs+Q1C;EuEp+QM;;IAEE,gCAAgC;EvEs+QxC;EuEr/QM;IAAwB,0BAA2B;EvEw/QzD;EuEv/QM;;IAEE,8BAA+B;EvEy/QvC;EuEv/QM;;IAEE,gCAAiC;EvEy/QzC;EuEv/QM;;IAEE,iCAAkC;EvEy/Q1C;EuEv/QM;;IAEE,+BAAgC;EvEy/QxC;EuExgRM;IAAwB,wBAA2B;EvE2gRzD;EuE1gRM;;IAEE,4BAA+B;EvE4gRvC;EuE1gRM;;IAEE,8BAAiC;EvE4gRzC;EuE1gRM;;IAEE,+BAAkC;EvE4gR1C;EuE1gRM;;IAEE,6BAAgC;EvE4gRxC;EuE3hRM;IAAwB,0BAA2B;EvE8hRzD;EuE7hRM;;IAEE,8BAA+B;EvE+hRvC;EuE7hRM;;IAEE,gCAAiC;EvE+hRzC;EuE7hRM;;IAEE,iCAAkC;EvE+hR1C;EuE7hRM;;IAEE,+BAAgC;EvE+hRxC;EuE9iRM;IAAwB,wBAA2B;EvEijRzD;EuEhjRM;;IAEE,4BAA+B;EvEkjRvC;EuEhjRM;;IAEE,8BAAiC;EvEkjRzC;EuEhjRM;;IAEE,+BAAkC;EvEkjR1C;EuEhjRM;;IAEE,6BAAgC;EvEkjRxC;EuE5iRE;IAAmB,uBAAuB;EvE+iR5C;EuE9iRE;;IAEE,2BAA2B;EvEgjR/B;EuE9iRE;;IAEE,6BAA6B;EvEgjRjC;EuE9iRE;;IAEE,8BAA8B;EvEgjRlC;EuE9iRE;;IAEE,4BAA4B;EvEgjRhC;AACF;;Ac1jRI;EyDlDI;IAAgC,oBAA4B;EvEinRlE;EuEhnRM;;IAEE,wBAAoC;EvEknR5C;EuEhnRM;;IAEE,0BAAwC;EvEknRhD;EuEhnRM;;IAEE,2BAA0C;EvEknRlD;EuEhnRM;;IAEE,yBAAsC;EvEknR9C;EuEjoRM;IAAgC,0BAA4B;EvEooRlE;EuEnoRM;;IAEE,8BAAoC;EvEqoR5C;EuEnoRM;;IAEE,gCAAwC;EvEqoRhD;EuEnoRM;;IAEE,iCAA0C;EvEqoRlD;EuEnoRM;;IAEE,+BAAsC;EvEqoR9C;EuEppRM;IAAgC,yBAA4B;EvEupRlE;EuEtpRM;;IAEE,6BAAoC;EvEwpR5C;EuEtpRM;;IAEE,+BAAwC;EvEwpRhD;EuEtpRM;;IAEE,gCAA0C;EvEwpRlD;EuEtpRM;;IAEE,8BAAsC;EvEwpR9C;EuEvqRM;IAAgC,uBAA4B;EvE0qRlE;EuEzqRM;;IAEE,2BAAoC;EvE2qR5C;EuEzqRM;;IAEE,6BAAwC;EvE2qRhD;EuEzqRM;;IAEE,8BAA0C;EvE2qRlD;EuEzqRM;;IAEE,4BAAsC;EvE2qR9C;EuE1rRM;IAAgC,yBAA4B;EvE6rRlE;EuE5rRM;;IAEE,6BAAoC;EvE8rR5C;EuE5rRM;;IAEE,+BAAwC;EvE8rRhD;EuE5rRM;;IAEE,gCAA0C;EvE8rRlD;EuE5rRM;;IAEE,8BAAsC;EvE8rR9C;EuE7sRM;IAAgC,uBAA4B;EvEgtRlE;EuE/sRM;;IAEE,2BAAoC;EvEitR5C;EuE/sRM;;IAEE,6BAAwC;EvEitRhD;EuE/sRM;;IAEE,8BAA0C;EvEitRlD;EuE/sRM;;IAEE,4BAAsC;EvEitR9C;EuEhuRM;IAAgC,qBAA4B;EvEmuRlE;EuEluRM;;IAEE,yBAAoC;EvEouR5C;EuEluRM;;IAEE,2BAAwC;EvEouRhD;EuEluRM;;IAEE,4BAA0C;EvEouRlD;EuEluRM;;IAEE,0BAAsC;EvEouR9C;EuEnvRM;IAAgC,2BAA4B;EvEsvRlE;EuErvRM;;IAEE,+BAAoC;EvEuvR5C;EuErvRM;;IAEE,iCAAwC;EvEuvRhD;EuErvRM;;IAEE,kCAA0C;EvEuvRlD;EuErvRM;;IAEE,gCAAsC;EvEuvR9C;EuEtwRM;IAAgC,0BAA4B;EvEywRlE;EuExwRM;;IAEE,8BAAoC;EvE0wR5C;EuExwRM;;IAEE,gCAAwC;EvE0wRhD;EuExwRM;;IAEE,iCAA0C;EvE0wRlD;EuExwRM;;IAEE,+BAAsC;EvE0wR9C;EuEzxRM;IAAgC,wBAA4B;EvE4xRlE;EuE3xRM;;IAEE,4BAAoC;EvE6xR5C;EuE3xRM;;IAEE,8BAAwC;EvE6xRhD;EuE3xRM;;IAEE,+BAA0C;EvE6xRlD;EuE3xRM;;IAEE,6BAAsC;EvE6xR9C;EuE5yRM;IAAgC,0BAA4B;EvE+yRlE;EuE9yRM;;IAEE,8BAAoC;EvEgzR5C;EuE9yRM;;IAEE,gCAAwC;EvEgzRhD;EuE9yRM;;IAEE,iCAA0C;EvEgzRlD;EuE9yRM;;IAEE,+BAAsC;EvEgzR9C;EuE/zRM;IAAgC,wBAA4B;EvEk0RlE;EuEj0RM;;IAEE,4BAAoC;EvEm0R5C;EuEj0RM;;IAEE,8BAAwC;EvEm0RhD;EuEj0RM;;IAEE,+BAA0C;EvEm0RlD;EuEj0RM;;IAEE,6BAAsC;EvEm0R9C;EuE3zRM;IAAwB,2BAA2B;EvE8zRzD;EuE7zRM;;IAEE,+BAA+B;EvE+zRvC;EuE7zRM;;IAEE,iCAAiC;EvE+zRzC;EuE7zRM;;IAEE,kCAAkC;EvE+zR1C;EuE7zRM;;IAEE,gCAAgC;EvE+zRxC;EuE90RM;IAAwB,0BAA2B;EvEi1RzD;EuEh1RM;;IAEE,8BAA+B;EvEk1RvC;EuEh1RM;;IAEE,gCAAiC;EvEk1RzC;EuEh1RM;;IAEE,iCAAkC;EvEk1R1C;EuEh1RM;;IAEE,+BAAgC;EvEk1RxC;EuEj2RM;IAAwB,wBAA2B;EvEo2RzD;EuEn2RM;;IAEE,4BAA+B;EvEq2RvC;EuEn2RM;;IAEE,8BAAiC;EvEq2RzC;EuEn2RM;;IAEE,+BAAkC;EvEq2R1C;EuEn2RM;;IAEE,6BAAgC;EvEq2RxC;EuEp3RM;IAAwB,0BAA2B;EvEu3RzD;EuEt3RM;;IAEE,8BAA+B;EvEw3RvC;EuEt3RM;;IAEE,gCAAiC;EvEw3RzC;EuEt3RM;;IAEE,iCAAkC;EvEw3R1C;EuEt3RM;;IAEE,+BAAgC;EvEw3RxC;EuEv4RM;IAAwB,wBAA2B;EvE04RzD;EuEz4RM;;IAEE,4BAA+B;EvE24RvC;EuEz4RM;;IAEE,8BAAiC;EvE24RzC;EuEz4RM;;IAEE,+BAAkC;EvE24R1C;EuEz4RM;;IAEE,6BAAgC;EvE24RxC;EuEr4RE;IAAmB,uBAAuB;EvEw4R5C;EuEv4RE;;IAEE,2BAA2B;EvEy4R/B;EuEv4RE;;IAEE,6BAA6B;EvEy4RjC;EuEv4RE;;IAEE,8BAA8B;EvEy4RlC;EuEv4RE;;IAEE,4BAA4B;EvEy4RhC;AACF;;AwEz8RA;EAAkB,4GAA8C;AxE68RhE;;AwEz8RA;EAAiB,8BAA8B;AxE68R/C;;AwE58RA;EAAiB,8BAA8B;AxEg9R/C;;AwE/8RA;EAAiB,8BAA8B;AxEm9R/C;;AwEl9RA;ECTE,gBAAgB;EAChB,uBAAuB;EACvB,mBAAmB;AzE+9RrB;;AwEh9RI;EAAwB,2BAA2B;AxEo9RvD;;AwEn9RI;EAAwB,4BAA4B;AxEu9RxD;;AwEt9RI;EAAwB,6BAA6B;AxE09RzD;;Acr7RI;E0DvCA;IAAwB,2BAA2B;ExEi+RrD;EwEh+RE;IAAwB,4BAA4B;ExEm+RtD;EwEl+RE;IAAwB,6BAA6B;ExEq+RvD;AACF;;Acj8RI;E0DvCA;IAAwB,2BAA2B;ExE6+RrD;EwE5+RE;IAAwB,4BAA4B;ExE++RtD;EwE9+RE;IAAwB,6BAA6B;ExEi/RvD;AACF;;Ac78RI;E0DvCA;IAAwB,2BAA2B;ExEy/RrD;EwEx/RE;IAAwB,4BAA4B;ExE2/RtD;EwE1/RE;IAAwB,6BAA6B;ExE6/RvD;AACF;;Acz9RI;E0DvCA;IAAwB,2BAA2B;ExEqgSrD;EwEpgSE;IAAwB,4BAA4B;ExEugStD;EwEtgSE;IAAwB,6BAA6B;ExEygSvD;AACF;;AwEpgSA;EAAmB,oCAAoC;AxEwgSvD;;AwEvgSA;EAAmB,oCAAoC;AxE2gSvD;;AwE1gSA;EAAmB,qCAAqC;AxE8gSxD;;AwE1gSA;EAAuB,2BAA0C;AxE8gSjE;;AwE7gSA;EAAuB,+BAA4C;AxEihSnE;;AwEhhSA;EAAuB,2BAA2C;AxEohSlE;;AwEnhSA;EAAuB,2BAAyC;AxEuhShE;;AwEthSA;EAAuB,8BAA2C;AxE0hSlE;;AwEzhSA;EAAuB,6BAA6B;AxE6hSpD;;AwEzhSA;EAAc,sBAAwB;AxE6hStC;;A0EpkSE;EACE,yBAAwB;A1EukS5B;;AK7jSE;EqELM,yBAA0E;A1EskSlF;;A0E5kSE;EACE,yBAAwB;A1E+kS5B;;AKrkSE;EqELM,yBAA0E;A1E8kSlF;;A0EplSE;EACE,yBAAwB;A1EulS5B;;AK7kSE;EqELM,yBAA0E;A1EslSlF;;A0E5lSE;EACE,yBAAwB;A1E+lS5B;;AKrlSE;EqELM,yBAA0E;A1E8lSlF;;A0EpmSE;EACE,yBAAwB;A1EumS5B;;AK7lSE;EqELM,yBAA0E;A1EsmSlF;;A0E5mSE;EACE,yBAAwB;A1E+mS5B;;AKrmSE;EqELM,yBAA0E;A1E8mSlF;;A0EpnSE;EACE,yBAAwB;A1EunS5B;;AK7mSE;EqELM,yBAA0E;A1EsnSlF;;A0E5nSE;EACE,yBAAwB;A1E+nS5B;;AKrnSE;EqELM,yBAA0E;A1E8nSlF;;AwEvlSA;EAAa,yBAA6B;AxE2lS1C;;AwE1lSA;EAAc,yBAA6B;AxE8lS3C;;AwE5lSA;EAAiB,oCAAkC;AxEgmSnD;;AwE/lSA;EAAiB,0CAAkC;AxEmmSnD;;AwE/lSA;EGvDE,WAAW;EACX,kBAAkB;EAClB,iBAAiB;EACjB,6BAA6B;EAC7B,SAAS;A3E0pSX;;AwEnmSA;EAAwB,gCAAgC;AxEumSxD;;AwErmSA;EACE,iCAAiC;EACjC,oCAAoC;AxEwmStC;;AwEnmSA;EAAc,yBAAyB;AxEumSvC;;A4ExqSA;EACE,8BAA8B;A5E2qShC;;A4ExqSA;EACE,6BAA6B;A5E2qS/B;;A6E3qSE;E3EOF;;;I2EDM,4BAA4B;IAE5B,2BAA2B;E7E2qS/B;E6ExqSE;IAEI,0BAA0B;E7EyqShC;E6EhqSE;IACE,6BAA6B;E7EkqSjC;EEn+RF;I2EhLM,gCAAgC;E7EspSpC;E6EppSE;;IAEE,yB1EzCY;I0E0CZ,wBAAwB;E7EspS5B;E6E9oSE;IACE,2BAA2B;E7EgpS/B;E6E7oSE;;IAEE,wBAAwB;E7E+oS5B;E6E5oSE;;;IAGE,UAAU;IACV,SAAS;E7E8oSb;E6E3oSE;;IAEE,uBAAuB;E7E6oS3B;E6EroSE;IACE,Q1EwgCgC;EH+nQpC;EEnrSF;I2E+CM,2BAA2C;E7EuoS/C;EY9tSA;IiE0FI,2BAA2C;E7EuoS/C;EiCrtSF;I4CmFM,aAAa;E7EqoSjB;EsCpuSF;IuCkGM,sB1EtFS;EH2tSb;EgBxuSF;I6DuGM,oCAAoC;E7EooSxC;E6EroSE;;IAKI,iCAAmC;E7EooSzC;EgBvsSF;;I6D0EQ,oCAAsC;E7EioS5C;EgBtnSF;I6DNM,cAAc;E7E+nSlB;EiBrvSA;;;;I4D4HM,qB1EvHU;EHsvShB;EgBjpSF;I6DuBM,cAAc;IACd,qB1E7HY;EH0vShB;AACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"code\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"input-group\";\n@import \"custom-forms\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"jumbotron\";\n@import \"alert\";\n@import \"progress\";\n@import \"media\";\n@import \"list-group\";\n@import \"close\";\n@import \"toasts\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"spinners\";\n@import \"utilities\";\n@import \"print\";\n","/*!\n * Bootstrap v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n --blue: #007bff;\n --indigo: #6610f2;\n --purple: #6f42c1;\n --pink: #e83e8c;\n --red: #dc3545;\n --orange: #fd7e14;\n --yellow: #ffc107;\n --green: #28a745;\n --teal: #20c997;\n --cyan: #17a2b8;\n --white: #fff;\n --gray: #6c757d;\n --gray-dark: #343a40;\n --primary: #007bff;\n --secondary: #6c757d;\n --success: #28a745;\n --info: #17a2b8;\n --warning: #ffc107;\n --danger: #dc3545;\n --light: #f8f9fa;\n --dark: #343a40;\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 992px;\n --breakpoint-xl: 1200px;\n --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\nh1, .h1 {\n font-size: 2.5rem;\n}\n\nh2, .h2 {\n font-size: 2rem;\n}\n\nh3, .h3 {\n font-size: 1.75rem;\n}\n\nh4, .h4 {\n font-size: 1.5rem;\n}\n\nh5, .h5 {\n font-size: 1.25rem;\n}\n\nh6, .h6 {\n font-size: 1rem;\n}\n\n.lead {\n font-size: 1.25rem;\n font-weight: 300;\n}\n\n.display-1 {\n font-size: 6rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-2 {\n font-size: 5.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-3 {\n font-size: 4.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-4 {\n font-size: 3.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\nhr {\n margin-top: 1rem;\n margin-bottom: 1rem;\n border: 0;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n font-size: 80%;\n font-weight: 400;\n}\n\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline-item {\n display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n.blockquote {\n margin-bottom: 1rem;\n font-size: 1.25rem;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%;\n color: #6c757d;\n}\n\n.blockquote-footer::before {\n content: \"\\2014\\00A0\";\n}\n\n.img-fluid {\n max-width: 100%;\n height: auto;\n}\n\n.img-thumbnail {\n padding: 0.25rem;\n background-color: #fff;\n border: 1px solid #dee2e6;\n border-radius: 0.25rem;\n max-width: 100%;\n height: auto;\n}\n\n.figure {\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: 0.5rem;\n line-height: 1;\n}\n\n.figure-caption {\n font-size: 90%;\n color: #6c757d;\n}\n\ncode {\n font-size: 87.5%;\n color: #e83e8c;\n word-break: break-word;\n}\n\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 87.5%;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\n\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n}\n\npre {\n display: block;\n font-size: 87.5%;\n color: #212529;\n}\n\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.table {\n width: 100%;\n margin-bottom: 1rem;\n color: #212529;\n}\n\n.table th,\n.table td {\n padding: 0.75rem;\n vertical-align: top;\n border-top: 1px solid #dee2e6;\n}\n\n.table thead th {\n vertical-align: bottom;\n border-bottom: 2px solid #dee2e6;\n}\n\n.table tbody + tbody {\n border-top: 2px solid #dee2e6;\n}\n\n.table-sm th,\n.table-sm td {\n padding: 0.3rem;\n}\n\n.table-bordered {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered th,\n.table-bordered td {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n border-bottom-width: 2px;\n}\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n border: 0;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n color: #212529;\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n background-color: #b8daff;\n}\n\n.table-primary th,\n.table-primary td,\n.table-primary thead th,\n.table-primary tbody + tbody {\n border-color: #7abaff;\n}\n\n.table-hover .table-primary:hover {\n background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n background-color: #d6d8db;\n}\n\n.table-secondary th,\n.table-secondary td,\n.table-secondary thead th,\n.table-secondary tbody + tbody {\n border-color: #b3b7bb;\n}\n\n.table-hover .table-secondary:hover {\n background-color: #c8cbcf;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n background-color: #c8cbcf;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n background-color: #c3e6cb;\n}\n\n.table-success th,\n.table-success td,\n.table-success thead th,\n.table-success tbody + tbody {\n border-color: #8fd19e;\n}\n\n.table-hover .table-success:hover {\n background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n background-color: #bee5eb;\n}\n\n.table-info th,\n.table-info td,\n.table-info thead th,\n.table-info tbody + tbody {\n border-color: #86cfda;\n}\n\n.table-hover .table-info:hover {\n background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n background-color: #ffeeba;\n}\n\n.table-warning th,\n.table-warning td,\n.table-warning thead th,\n.table-warning tbody + tbody {\n border-color: #ffdf7e;\n}\n\n.table-hover .table-warning:hover {\n background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n background-color: #f5c6cb;\n}\n\n.table-danger th,\n.table-danger td,\n.table-danger thead th,\n.table-danger tbody + tbody {\n border-color: #ed969e;\n}\n\n.table-hover .table-danger:hover {\n background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n background-color: #fdfdfe;\n}\n\n.table-light th,\n.table-light td,\n.table-light thead th,\n.table-light tbody + tbody {\n border-color: #fbfcfc;\n}\n\n.table-hover .table-light:hover {\n background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n background-color: #c6c8ca;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th,\n.table-dark tbody + tbody {\n border-color: #95999c;\n}\n\n.table-hover .table-dark:hover {\n background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n color: #fff;\n background-color: #343a40;\n border-color: #454d55;\n}\n\n.table .thead-light th {\n color: #495057;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.table-dark {\n color: #fff;\n background-color: #343a40;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n border-color: #454d55;\n}\n\n.table-dark.table-bordered {\n border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n color: #fff;\n background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575.98px) {\n .table-responsive-sm {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-sm > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 767.98px) {\n .table-responsive-md {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-md > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 991.98px) {\n .table-responsive-lg {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-lg > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 1199.98px) {\n .table-responsive-xl {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .table-responsive-xl > .table-bordered {\n border: 0;\n }\n}\n\n.table-responsive {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.table-responsive > .table-bordered {\n border: 0;\n}\n\n.form-control {\n display: block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .form-control {\n transition: none;\n }\n}\n\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n\n.form-control:focus {\n color: #495057;\n background-color: #fff;\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::placeholder {\n color: #6c757d;\n opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1;\n}\n\nselect.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n.col-form-label {\n padding-top: calc(0.375rem + 1px);\n padding-bottom: calc(0.375rem + 1px);\n margin-bottom: 0;\n font-size: inherit;\n line-height: 1.5;\n}\n\n.col-form-label-lg {\n padding-top: calc(0.5rem + 1px);\n padding-bottom: calc(0.5rem + 1px);\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.col-form-label-sm {\n padding-top: calc(0.25rem + 1px);\n padding-bottom: calc(0.25rem + 1px);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n margin-bottom: 0;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0;\n}\n\n.form-control-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.form-control-lg {\n height: calc(1.5em + 1rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\nselect.form-control[size], select.form-control[multiple] {\n height: auto;\n}\n\ntextarea.form-control {\n height: auto;\n}\n\n.form-group {\n margin-bottom: 1rem;\n}\n\n.form-text {\n display: block;\n margin-top: 0.25rem;\n}\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -5px;\n margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.form-check {\n position: relative;\n display: block;\n padding-left: 1.25rem;\n}\n\n.form-check-input {\n position: absolute;\n margin-top: 0.3rem;\n margin-left: -1.25rem;\n}\n\n.form-check-input:disabled ~ .form-check-label {\n color: #6c757d;\n}\n\n.form-check-label {\n margin-bottom: 0;\n}\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0;\n margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: 0.3125rem;\n margin-left: 0;\n}\n\n.valid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #28a745;\n}\n\n.valid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(40, 167, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid {\n border-color: #28a745;\n padding-right: calc(1.5em + 0.75rem);\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\");\n background-repeat: no-repeat;\n background-position: center right calc(0.375em + 0.1875rem);\n background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated textarea.form-control:valid, textarea.form-control.is-valid {\n padding-right: calc(1.5em + 0.75rem);\n background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:valid, .custom-select.is-valid {\n border-color: #28a745;\n padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-select:valid ~ .valid-feedback,\n.was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:valid ~ .valid-feedback,\n.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,\n.form-control-file.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n color: #28a745;\n}\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n border-color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .valid-feedback,\n.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,\n.custom-control-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n border-color: #34ce57;\n background-color: #34ce57;\n}\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .valid-feedback,\n.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,\n.custom-file-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #dc3545;\n}\n\n.invalid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(220, 53, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid {\n border-color: #dc3545;\n padding-right: calc(1.5em + 0.75rem);\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\");\n background-repeat: no-repeat;\n background-position: center right calc(0.375em + 0.1875rem);\n background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {\n padding-right: calc(1.5em + 0.75rem);\n background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .custom-select:invalid, .custom-select.is-invalid {\n border-color: #dc3545;\n padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem);\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px, url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n\n.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-select:invalid ~ .invalid-feedback,\n.was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:invalid ~ .invalid-feedback,\n.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,\n.form-control-file.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n color: #dc3545;\n}\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n border-color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .invalid-feedback,\n.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,\n.custom-control-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n border-color: #e4606d;\n background-color: #e4606d;\n}\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .invalid-feedback,\n.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,\n.custom-file-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center;\n}\n\n.form-inline .form-check {\n width: 100%;\n}\n\n@media (min-width: 576px) {\n .form-inline label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0;\n }\n .form-inline .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-plaintext {\n display: inline-block;\n }\n .form-inline .input-group,\n .form-inline .custom-select {\n width: auto;\n }\n .form-inline .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0;\n }\n .form-inline .form-check-input {\n position: relative;\n flex-shrink: 0;\n margin-top: 0;\n margin-right: 0.25rem;\n margin-left: 0;\n }\n .form-inline .custom-control {\n align-items: center;\n justify-content: center;\n }\n .form-inline .custom-control-label {\n margin-bottom: 0;\n }\n}\n\n.btn {\n display: inline-block;\n font-weight: 400;\n color: #212529;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n background-color: transparent;\n border: 1px solid transparent;\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .btn {\n transition: none;\n }\n}\n\n.btn:hover {\n color: #212529;\n text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n opacity: 0.65;\n}\n\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none;\n}\n\n.btn-primary {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:hover {\n color: #fff;\n background-color: #0069d9;\n border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n color: #fff;\n background-color: #0062cc;\n border-color: #005cbf;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);\n}\n\n.btn-secondary {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:hover {\n color: #fff;\n background-color: #5a6268;\n border-color: #545b62;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n color: #fff;\n background-color: #545b62;\n border-color: #4e555b;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);\n}\n\n.btn-success {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:hover {\n color: #fff;\n background-color: #218838;\n border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n color: #fff;\n background-color: #1e7e34;\n border-color: #1c7430;\n}\n\n.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);\n}\n\n.btn-info {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:hover {\n color: #fff;\n background-color: #138496;\n border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n color: #fff;\n background-color: #117a8b;\n border-color: #10707f;\n}\n\n.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n}\n\n.btn-warning {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:hover {\n color: #212529;\n background-color: #e0a800;\n border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n color: #212529;\n background-color: #d39e00;\n border-color: #c69500;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);\n}\n\n.btn-danger {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:hover {\n color: #fff;\n background-color: #c82333;\n border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n color: #fff;\n background-color: #bd2130;\n border-color: #b21f2d;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n}\n\n.btn-light {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n color: #212529;\n background-color: #e2e6ea;\n border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n color: #212529;\n background-color: #dae0e5;\n border-color: #d3d9df;\n}\n\n.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);\n}\n\n.btn-dark {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:hover {\n color: #fff;\n background-color: #23272b;\n border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n color: #fff;\n background-color: #1d2124;\n border-color: #171a1d;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);\n}\n\n.btn-outline-primary {\n color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:hover {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-success {\n color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n color: #28a745;\n background-color: transparent;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n color: #17a2b8;\n background-color: transparent;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n color: #ffc107;\n background-color: transparent;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n color: #dc3545;\n background-color: transparent;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n color: #f8f9fa;\n background-color: transparent;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n color: #343a40;\n background-color: transparent;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n font-weight: 400;\n color: #007bff;\n text-decoration: none;\n}\n\n.btn-link:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\n.btn-link:focus, .btn-link.focus {\n text-decoration: underline;\n box-shadow: none;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n color: #6c757d;\n pointer-events: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n.btn-block + .btn-block {\n margin-top: 0.5rem;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n\n.fade {\n transition: opacity 0.15s linear;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .fade {\n transition: none;\n }\n}\n\n.fade:not(.show) {\n opacity: 0;\n}\n\n.collapse:not(.show) {\n display: none;\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n transition: height 0.35s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .collapsing {\n transition: none;\n }\n}\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle {\n white-space: nowrap;\n}\n\n.dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem;\n}\n\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n\n@media (min-width: 576px) {\n .dropdown-menu-sm-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-sm-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 768px) {\n .dropdown-menu-md-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-md-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 992px) {\n .dropdown-menu-lg-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-lg-right {\n right: 0;\n left: auto;\n }\n}\n\n@media (min-width: 1200px) {\n .dropdown-menu-xl-left {\n right: auto;\n left: 0;\n }\n .dropdown-menu-xl-right {\n right: 0;\n left: auto;\n }\n}\n\n.dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem;\n}\n\n.dropright .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid;\n}\n\n.dropright .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-toggle::after {\n vertical-align: 0;\n}\n\n.dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem;\n}\n\n.dropleft .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n}\n\n.dropleft .dropdown-toggle::after {\n display: none;\n}\n\n.dropleft .dropdown-toggle::before {\n display: inline-block;\n margin-right: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0.3em solid;\n border-bottom: 0.3em solid transparent;\n}\n\n.dropleft .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle::before {\n vertical-align: 0;\n}\n\n.dropdown-menu[x-placement^=\"top\"], .dropdown-menu[x-placement^=\"right\"], .dropdown-menu[x-placement^=\"bottom\"], .dropdown-menu[x-placement^=\"left\"] {\n right: auto;\n bottom: auto;\n}\n\n.dropdown-divider {\n height: 0;\n margin: 0.5rem 0;\n overflow: hidden;\n border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0;\n}\n\n.dropdown-item:hover, .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n color: #6c757d;\n pointer-events: none;\n background-color: transparent;\n}\n\n.dropdown-menu.show {\n display: block;\n}\n\n.dropdown-header {\n display: block;\n padding: 0.5rem 1.5rem;\n margin-bottom: 0;\n font-size: 0.875rem;\n color: #6c757d;\n white-space: nowrap;\n}\n\n.dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529;\n}\n\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n flex: 1 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n z-index: 1;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n z-index: 1;\n}\n\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n width: auto;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) {\n margin-left: -1px;\n}\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n padding-right: 0.5625rem;\n padding-left: 0.5625rem;\n}\n\n.dropdown-toggle-split::after,\n.dropup .dropdown-toggle-split::after,\n.dropright .dropdown-toggle-split::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle-split::before {\n margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n padding-right: 0.375rem;\n padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n padding-right: 0.75rem;\n padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n width: 100%;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) {\n margin-top: -1px;\n}\n\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n margin-bottom: 0;\n}\n\n.btn-group-toggle > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn input[type=\"checkbox\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n width: 100%;\n}\n\n.input-group > .form-control,\n.input-group > .form-control-plaintext,\n.input-group > .custom-select,\n.input-group > .custom-file {\n position: relative;\n flex: 1 1 auto;\n width: 1%;\n margin-bottom: 0;\n}\n\n.input-group > .form-control + .form-control,\n.input-group > .form-control + .custom-select,\n.input-group > .form-control + .custom-file,\n.input-group > .form-control-plaintext + .form-control,\n.input-group > .form-control-plaintext + .custom-select,\n.input-group > .form-control-plaintext + .custom-file,\n.input-group > .custom-select + .form-control,\n.input-group > .custom-select + .custom-select,\n.input-group > .custom-select + .custom-file,\n.input-group > .custom-file + .form-control,\n.input-group > .custom-file + .custom-select,\n.input-group > .custom-file + .custom-file {\n margin-left: -1px;\n}\n\n.input-group > .form-control:focus,\n.input-group > .custom-select:focus,\n.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3;\n}\n\n.input-group > .custom-file .custom-file-input:focus {\n z-index: 4;\n}\n\n.input-group > .form-control:not(:last-child),\n.input-group > .custom-select:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .form-control:not(:first-child),\n.input-group > .custom-select:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group > .custom-file {\n display: flex;\n align-items: center;\n}\n\n.input-group > .custom-file:not(:last-child) .custom-file-label,\n.input-group > .custom-file:not(:last-child) .custom-file-label::after {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .custom-file:not(:first-child) .custom-file-label {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group-prepend,\n.input-group-append {\n display: flex;\n}\n\n.input-group-prepend .btn,\n.input-group-append .btn {\n position: relative;\n z-index: 2;\n}\n\n.input-group-prepend .btn:focus,\n.input-group-append .btn:focus {\n z-index: 3;\n}\n\n.input-group-prepend .btn + .btn,\n.input-group-prepend .btn + .input-group-text,\n.input-group-prepend .input-group-text + .input-group-text,\n.input-group-prepend .input-group-text + .btn,\n.input-group-append .btn + .btn,\n.input-group-append .btn + .input-group-text,\n.input-group-append .input-group-text + .input-group-text,\n.input-group-append .input-group-text + .btn {\n margin-left: -1px;\n}\n\n.input-group-prepend {\n margin-right: -1px;\n}\n\n.input-group-append {\n margin-left: -1px;\n}\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: 0.375rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n text-align: center;\n white-space: nowrap;\n background-color: #e9ecef;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.input-group-text input[type=\"radio\"],\n.input-group-text input[type=\"checkbox\"] {\n margin-top: 0;\n}\n\n.input-group-lg > .form-control:not(textarea),\n.input-group-lg > .custom-select {\n height: calc(1.5em + 1rem + 2px);\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .custom-select,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control:not(textarea),\n.input-group-sm > .custom-select {\n height: calc(1.5em + 0.5rem + 2px);\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .custom-select,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.input-group-lg > .custom-select,\n.input-group-sm > .custom-select {\n padding-right: 1.75rem;\n}\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.custom-control {\n position: relative;\n display: block;\n min-height: 1.5rem;\n padding-left: 1.5rem;\n}\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: 1rem;\n}\n\n.custom-control-input {\n position: absolute;\n z-index: -1;\n opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-label::before {\n color: #fff;\n border-color: #007bff;\n background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:focus:not(:checked) ~ .custom-control-label::before {\n border-color: #80bdff;\n}\n\n.custom-control-input:not(:disabled):active ~ .custom-control-label::before {\n color: #fff;\n background-color: #b3d7ff;\n border-color: #b3d7ff;\n}\n\n.custom-control-input:disabled ~ .custom-control-label {\n color: #6c757d;\n}\n\n.custom-control-input:disabled ~ .custom-control-label::before {\n background-color: #e9ecef;\n}\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0;\n vertical-align: top;\n}\n\n.custom-control-label::before {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n content: \"\";\n background-color: #fff;\n border: #adb5bd solid 1px;\n}\n\n.custom-control-label::after {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n content: \"\";\n background: no-repeat 50% / 50% 50%;\n}\n\n.custom-checkbox .custom-control-label::before {\n border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n border-color: #007bff;\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e\");\n}\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-radio .custom-control-label::before {\n border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");\n}\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-switch {\n padding-left: 2.25rem;\n}\n\n.custom-switch .custom-control-label::before {\n left: -2.25rem;\n width: 1.75rem;\n pointer-events: all;\n border-radius: 0.5rem;\n}\n\n.custom-switch .custom-control-label::after {\n top: calc(0.25rem + 2px);\n left: calc(-2.25rem + 2px);\n width: calc(1rem - 4px);\n height: calc(1rem - 4px);\n background-color: #adb5bd;\n border-radius: 0.5rem;\n transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-switch .custom-control-label::after {\n transition: none;\n }\n}\n\n.custom-switch .custom-control-input:checked ~ .custom-control-label::after {\n background-color: #fff;\n transform: translateX(0.75rem);\n}\n\n.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n vertical-align: middle;\n background: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\") no-repeat right 0.75rem center/8px 10px;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n appearance: none;\n}\n\n.custom-select:focus {\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-select:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.custom-select[multiple], .custom-select[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: 0.75rem;\n background-image: none;\n}\n\n.custom-select:disabled {\n color: #6c757d;\n background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n display: none;\n}\n\n.custom-select-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n padding-left: 0.5rem;\n font-size: 0.875rem;\n}\n\n.custom-select-lg {\n height: calc(1.5em + 1rem + 2px);\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n padding-left: 1rem;\n font-size: 1.25rem;\n}\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: calc(1.5em + 0.75rem + 2px);\n margin: 0;\n opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-label {\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-file-input:disabled ~ .custom-file-label {\n background-color: #e9ecef;\n}\n\n.custom-file-input:lang(en) ~ .custom-file-label::after {\n content: \"Browse\";\n}\n\n.custom-file-input ~ .custom-file-label[data-browse]::after {\n content: attr(data-browse);\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: calc(1.5em + 0.75rem + 2px);\n padding: 0.375rem 0.75rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.custom-file-label::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: calc(1.5em + 0.75rem);\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n content: \"Browse\";\n background-color: #e9ecef;\n border-left: inherit;\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-range {\n width: 100%;\n height: calc(1rem + 0.4rem);\n padding: 0;\n background-color: transparent;\n appearance: none;\n}\n\n.custom-range:focus {\n outline: none;\n}\n\n.custom-range:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-moz-range-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-ms-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range::-moz-focus-outer {\n border: 0;\n}\n\n.custom-range::-webkit-slider-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: -0.25rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-webkit-slider-thumb {\n transition: none;\n }\n}\n\n.custom-range::-webkit-slider-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-webkit-slider-runnable-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-moz-range-thumb {\n width: 1rem;\n height: 1rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-moz-range-thumb {\n transition: none;\n }\n}\n\n.custom-range::-moz-range-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-moz-range-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: 0;\n margin-right: 0.2rem;\n margin-left: 0.2rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-range::-ms-thumb {\n transition: none;\n }\n}\n\n.custom-range::-ms-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-ms-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: transparent;\n border-color: transparent;\n border-width: 0.5rem;\n}\n\n.custom-range::-ms-fill-lower {\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-fill-upper {\n margin-right: 15px;\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range:disabled::-webkit-slider-thumb {\n background-color: #adb5bd;\n}\n\n.custom-range:disabled::-webkit-slider-runnable-track {\n cursor: default;\n}\n\n.custom-range:disabled::-moz-range-thumb {\n background-color: #adb5bd;\n}\n\n.custom-range:disabled::-moz-range-track {\n cursor: default;\n}\n\n.custom-range:disabled::-ms-thumb {\n background-color: #adb5bd;\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .custom-control-label::before,\n .custom-file-label,\n .custom-select {\n transition: none;\n }\n}\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.nav-link {\n display: block;\n padding: 0.5rem 1rem;\n}\n\n.nav-link:hover, .nav-link:focus {\n text-decoration: none;\n}\n\n.nav-link.disabled {\n color: #6c757d;\n pointer-events: none;\n cursor: default;\n}\n\n.nav-tabs {\n border-bottom: 1px solid #dee2e6;\n}\n\n.nav-tabs .nav-item {\n margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n border: 1px solid transparent;\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n border-color: #e9ecef #e9ecef #dee2e6;\n}\n\n.nav-tabs .nav-link.disabled {\n color: #6c757d;\n background-color: transparent;\n border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n color: #495057;\n background-color: #fff;\n border-color: #dee2e6 #dee2e6 #fff;\n}\n\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n color: #fff;\n background-color: #007bff;\n}\n\n.nav-fill .nav-item {\n flex: 1 1 auto;\n text-align: center;\n}\n\n.nav-justified .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center;\n}\n\n.tab-content > .tab-pane {\n display: none;\n}\n\n.tab-content > .active {\n display: block;\n}\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n}\n\n.navbar > .container,\n.navbar > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n\n.navbar-brand {\n display: inline-block;\n padding-top: 0.3125rem;\n padding-bottom: 0.3125rem;\n margin-right: 1rem;\n font-size: 1.25rem;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.navbar-brand:hover, .navbar-brand:focus {\n text-decoration: none;\n}\n\n.navbar-nav {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.navbar-nav .nav-link {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n position: static;\n float: none;\n}\n\n.navbar-text {\n display: inline-block;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n align-items: center;\n}\n\n.navbar-toggler {\n padding: 0.25rem 0.75rem;\n font-size: 1.25rem;\n line-height: 1;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.navbar-toggler:hover, .navbar-toggler:focus {\n text-decoration: none;\n}\n\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: \"\";\n background: no-repeat center center;\n background-size: 100% 100%;\n}\n\n@media (max-width: 575.98px) {\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 576px) {\n .navbar-expand-sm {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-sm .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-sm .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-sm .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-sm .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-sm .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 767.98px) {\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 768px) {\n .navbar-expand-md {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-md .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-md .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-md .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-md .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-md .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 991.98px) {\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 992px) {\n .navbar-expand-lg {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-lg .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-lg .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-lg .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-lg .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-lg .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 1199.98px) {\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .navbar-expand-xl {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-xl .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-xl .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-xl .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-xl .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-xl .navbar-toggler {\n display: none;\n }\n}\n\n.navbar-expand {\n flex-flow: row nowrap;\n justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n position: absolute;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n display: none;\n}\n\n.navbar-light .navbar-brand {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n color: rgba(0, 0, 0, 0.5);\n border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-light .navbar-text {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n color: #fff;\n}\n\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n color: rgba(255, 255, 255, 0.5);\n border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n\n.navbar-dark .navbar-text {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n color: #fff;\n}\n\n.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n color: #fff;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: border-box;\n border: 1px solid rgba(0, 0, 0, 0.125);\n border-radius: 0.25rem;\n}\n\n.card > hr {\n margin-right: 0;\n margin-left: 0;\n}\n\n.card > .list-group:first-child .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.card > .list-group:last-child .list-group-item:last-child {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.card-body {\n flex: 1 1 auto;\n padding: 1.25rem;\n}\n\n.card-title {\n margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n margin-top: -0.375rem;\n margin-bottom: 0;\n}\n\n.card-text:last-child {\n margin-bottom: 0;\n}\n\n.card-link:hover {\n text-decoration: none;\n}\n\n.card-link + .card-link {\n margin-left: 1.25rem;\n}\n\n.card-header {\n padding: 0.75rem 1.25rem;\n margin-bottom: 0;\n background-color: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-header + .list-group .list-group-item:first-child {\n border-top: 0;\n}\n\n.card-footer {\n padding: 0.75rem 1.25rem;\n background-color: rgba(0, 0, 0, 0.03);\n border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n margin-right: -0.625rem;\n margin-bottom: -0.75rem;\n margin-left: -0.625rem;\n border-bottom: 0;\n}\n\n.card-header-pills {\n margin-right: -0.625rem;\n margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: 1.25rem;\n}\n\n.card-img {\n width: 100%;\n border-radius: calc(0.25rem - 1px);\n}\n\n.card-img-top {\n width: 100%;\n border-top-left-radius: calc(0.25rem - 1px);\n border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img-bottom {\n width: 100%;\n border-bottom-right-radius: calc(0.25rem - 1px);\n border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck {\n display: flex;\n flex-direction: column;\n}\n\n.card-deck .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-deck {\n flex-flow: row wrap;\n margin-right: -15px;\n margin-left: -15px;\n }\n .card-deck .card {\n display: flex;\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: 15px;\n margin-bottom: 0;\n margin-left: 15px;\n }\n}\n\n.card-group {\n display: flex;\n flex-direction: column;\n}\n\n.card-group > .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-group {\n flex-flow: row wrap;\n }\n .card-group > .card {\n flex: 1 0 0%;\n margin-bottom: 0;\n }\n .card-group > .card + .card {\n margin-left: 0;\n border-left: 0;\n }\n .card-group > .card:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .card-group > .card:not(:last-child) .card-img-top,\n .card-group > .card:not(:last-child) .card-header {\n border-top-right-radius: 0;\n }\n .card-group > .card:not(:last-child) .card-img-bottom,\n .card-group > .card:not(:last-child) .card-footer {\n border-bottom-right-radius: 0;\n }\n .card-group > .card:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .card-group > .card:not(:first-child) .card-img-top,\n .card-group > .card:not(:first-child) .card-header {\n border-top-left-radius: 0;\n }\n .card-group > .card:not(:first-child) .card-img-bottom,\n .card-group > .card:not(:first-child) .card-footer {\n border-bottom-left-radius: 0;\n }\n}\n\n.card-columns .card {\n margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n .card-columns {\n column-count: 3;\n column-gap: 1.25rem;\n orphans: 1;\n widows: 1;\n }\n .card-columns .card {\n display: inline-block;\n width: 100%;\n }\n}\n\n.accordion > .card {\n overflow: hidden;\n}\n\n.accordion > .card:not(:first-of-type) .card-header:first-child {\n border-radius: 0;\n}\n\n.accordion > .card:not(:first-of-type):not(:last-of-type) {\n border-bottom: 0;\n border-radius: 0;\n}\n\n.accordion > .card:first-of-type {\n border-bottom: 0;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.accordion > .card:last-of-type {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.accordion > .card .card-header {\n margin-bottom: -1px;\n}\n\n.breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n list-style: none;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n padding-left: 0.5rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n display: inline-block;\n padding-right: 0.5rem;\n color: #6c757d;\n content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: none;\n}\n\n.breadcrumb-item.active {\n color: #6c757d;\n}\n\n.pagination {\n display: flex;\n padding-left: 0;\n list-style: none;\n border-radius: 0.25rem;\n}\n\n.page-link {\n position: relative;\n display: block;\n padding: 0.5rem 0.75rem;\n margin-left: -1px;\n line-height: 1.25;\n color: #007bff;\n background-color: #fff;\n border: 1px solid #dee2e6;\n}\n\n.page-link:hover {\n z-index: 2;\n color: #0056b3;\n text-decoration: none;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.page-link:focus {\n z-index: 2;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.page-item:first-child .page-link {\n margin-left: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n z-index: 1;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n color: #6c757d;\n pointer-events: none;\n cursor: auto;\n background-color: #fff;\n border-color: #dee2e6;\n}\n\n.pagination-lg .page-link {\n padding: 0.75rem 1.5rem;\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n border-top-left-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n border-top-right-radius: 0.3rem;\n border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n border-top-left-radius: 0.2rem;\n border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n border-top-right-radius: 0.2rem;\n border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n display: inline-block;\n padding: 0.25em 0.4em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .badge {\n transition: none;\n }\n}\n\na.badge:hover, a.badge:focus {\n text-decoration: none;\n}\n\n.badge:empty {\n display: none;\n}\n\n.btn .badge {\n position: relative;\n top: -1px;\n}\n\n.badge-pill {\n padding-right: 0.6em;\n padding-left: 0.6em;\n border-radius: 10rem;\n}\n\n.badge-primary {\n color: #fff;\n background-color: #007bff;\n}\n\na.badge-primary:hover, a.badge-primary:focus {\n color: #fff;\n background-color: #0062cc;\n}\n\na.badge-primary:focus, a.badge-primary.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.badge-secondary {\n color: #fff;\n background-color: #6c757d;\n}\n\na.badge-secondary:hover, a.badge-secondary:focus {\n color: #fff;\n background-color: #545b62;\n}\n\na.badge-secondary:focus, a.badge-secondary.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.badge-success {\n color: #fff;\n background-color: #28a745;\n}\n\na.badge-success:hover, a.badge-success:focus {\n color: #fff;\n background-color: #1e7e34;\n}\n\na.badge-success:focus, a.badge-success.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.badge-info {\n color: #fff;\n background-color: #17a2b8;\n}\n\na.badge-info:hover, a.badge-info:focus {\n color: #fff;\n background-color: #117a8b;\n}\n\na.badge-info:focus, a.badge-info.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.badge-warning {\n color: #212529;\n background-color: #ffc107;\n}\n\na.badge-warning:hover, a.badge-warning:focus {\n color: #212529;\n background-color: #d39e00;\n}\n\na.badge-warning:focus, a.badge-warning.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.badge-danger {\n color: #fff;\n background-color: #dc3545;\n}\n\na.badge-danger:hover, a.badge-danger:focus {\n color: #fff;\n background-color: #bd2130;\n}\n\na.badge-danger:focus, a.badge-danger.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.badge-light {\n color: #212529;\n background-color: #f8f9fa;\n}\n\na.badge-light:hover, a.badge-light:focus {\n color: #212529;\n background-color: #dae0e5;\n}\n\na.badge-light:focus, a.badge-light.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.badge-dark {\n color: #fff;\n background-color: #343a40;\n}\n\na.badge-dark:hover, a.badge-dark:focus {\n color: #fff;\n background-color: #1d2124;\n}\n\na.badge-dark:focus, a.badge-dark.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.jumbotron {\n padding: 2rem 1rem;\n margin-bottom: 2rem;\n background-color: #e9ecef;\n border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n .jumbotron {\n padding: 4rem 2rem;\n }\n}\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n border-radius: 0;\n}\n\n.alert {\n position: relative;\n padding: 0.75rem 1.25rem;\n margin-bottom: 1rem;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.alert-heading {\n color: inherit;\n}\n\n.alert-link {\n font-weight: 700;\n}\n\n.alert-dismissible {\n padding-right: 4rem;\n}\n\n.alert-dismissible .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: 0.75rem 1.25rem;\n color: inherit;\n}\n\n.alert-primary {\n color: #004085;\n background-color: #cce5ff;\n border-color: #b8daff;\n}\n\n.alert-primary hr {\n border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n color: #002752;\n}\n\n.alert-secondary {\n color: #383d41;\n background-color: #e2e3e5;\n border-color: #d6d8db;\n}\n\n.alert-secondary hr {\n border-top-color: #c8cbcf;\n}\n\n.alert-secondary .alert-link {\n color: #202326;\n}\n\n.alert-success {\n color: #155724;\n background-color: #d4edda;\n border-color: #c3e6cb;\n}\n\n.alert-success hr {\n border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n color: #0b2e13;\n}\n\n.alert-info {\n color: #0c5460;\n background-color: #d1ecf1;\n border-color: #bee5eb;\n}\n\n.alert-info hr {\n border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n color: #062c33;\n}\n\n.alert-warning {\n color: #856404;\n background-color: #fff3cd;\n border-color: #ffeeba;\n}\n\n.alert-warning hr {\n border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n color: #533f03;\n}\n\n.alert-danger {\n color: #721c24;\n background-color: #f8d7da;\n border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n color: #491217;\n}\n\n.alert-light {\n color: #818182;\n background-color: #fefefe;\n border-color: #fdfdfe;\n}\n\n.alert-light hr {\n border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n color: #686868;\n}\n\n.alert-dark {\n color: #1b1e21;\n background-color: #d6d8d9;\n border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n color: #040505;\n}\n\n@keyframes progress-bar-stripes {\n from {\n background-position: 1rem 0;\n }\n to {\n background-position: 0 0;\n }\n}\n\n.progress {\n display: flex;\n height: 1rem;\n overflow: hidden;\n font-size: 0.75rem;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n background-color: #007bff;\n transition: width 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none;\n }\n}\n\n.progress-bar-striped {\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n animation: progress-bar-stripes 1s linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .progress-bar-animated {\n animation: none;\n }\n}\n\n.media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n\n.list-group {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n}\n\n.list-group-item-action {\n width: 100%;\n color: #495057;\n text-align: inherit;\n}\n\n.list-group-item-action:hover, .list-group-item-action:focus {\n z-index: 1;\n color: #495057;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n color: #212529;\n background-color: #e9ecef;\n}\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 0.75rem 1.25rem;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n color: #6c757d;\n pointer-events: none;\n background-color: #fff;\n}\n\n.list-group-item.active {\n z-index: 2;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.list-group-horizontal {\n flex-direction: row;\n}\n\n.list-group-horizontal .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n}\n\n.list-group-horizontal .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n}\n\n.list-group-horizontal .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n}\n\n@media (min-width: 576px) {\n .list-group-horizontal-sm {\n flex-direction: row;\n }\n .list-group-horizontal-sm .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-sm .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-sm .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 768px) {\n .list-group-horizontal-md {\n flex-direction: row;\n }\n .list-group-horizontal-md .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-md .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-md .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 992px) {\n .list-group-horizontal-lg {\n flex-direction: row;\n }\n .list-group-horizontal-lg .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-lg .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-lg .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .list-group-horizontal-xl {\n flex-direction: row;\n }\n .list-group-horizontal-xl .list-group-item {\n margin-right: -1px;\n margin-bottom: 0;\n }\n .list-group-horizontal-xl .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n border-top-right-radius: 0;\n }\n .list-group-horizontal-xl .list-group-item:last-child {\n margin-right: 0;\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0;\n }\n}\n\n.list-group-flush .list-group-item {\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n.list-group-flush .list-group-item:last-child {\n margin-bottom: -1px;\n}\n\n.list-group-flush:first-child .list-group-item:first-child {\n border-top: 0;\n}\n\n.list-group-flush:last-child .list-group-item:last-child {\n margin-bottom: 0;\n border-bottom: 0;\n}\n\n.list-group-item-primary {\n color: #004085;\n background-color: #b8daff;\n}\n\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n color: #004085;\n background-color: #9fcdff;\n}\n\n.list-group-item-primary.list-group-item-action.active {\n color: #fff;\n background-color: #004085;\n border-color: #004085;\n}\n\n.list-group-item-secondary {\n color: #383d41;\n background-color: #d6d8db;\n}\n\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n color: #383d41;\n background-color: #c8cbcf;\n}\n\n.list-group-item-secondary.list-group-item-action.active {\n color: #fff;\n background-color: #383d41;\n border-color: #383d41;\n}\n\n.list-group-item-success {\n color: #155724;\n background-color: #c3e6cb;\n}\n\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n color: #155724;\n background-color: #b1dfbb;\n}\n\n.list-group-item-success.list-group-item-action.active {\n color: #fff;\n background-color: #155724;\n border-color: #155724;\n}\n\n.list-group-item-info {\n color: #0c5460;\n background-color: #bee5eb;\n}\n\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n color: #0c5460;\n background-color: #abdde5;\n}\n\n.list-group-item-info.list-group-item-action.active {\n color: #fff;\n background-color: #0c5460;\n border-color: #0c5460;\n}\n\n.list-group-item-warning {\n color: #856404;\n background-color: #ffeeba;\n}\n\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n color: #856404;\n background-color: #ffe8a1;\n}\n\n.list-group-item-warning.list-group-item-action.active {\n color: #fff;\n background-color: #856404;\n border-color: #856404;\n}\n\n.list-group-item-danger {\n color: #721c24;\n background-color: #f5c6cb;\n}\n\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n color: #721c24;\n background-color: #f1b0b7;\n}\n\n.list-group-item-danger.list-group-item-action.active {\n color: #fff;\n background-color: #721c24;\n border-color: #721c24;\n}\n\n.list-group-item-light {\n color: #818182;\n background-color: #fdfdfe;\n}\n\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n color: #818182;\n background-color: #ececf6;\n}\n\n.list-group-item-light.list-group-item-action.active {\n color: #fff;\n background-color: #818182;\n border-color: #818182;\n}\n\n.list-group-item-dark {\n color: #1b1e21;\n background-color: #c6c8ca;\n}\n\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n color: #1b1e21;\n background-color: #b9bbbe;\n}\n\n.list-group-item-dark.list-group-item-action.active {\n color: #fff;\n background-color: #1b1e21;\n border-color: #1b1e21;\n}\n\n.close {\n float: right;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: .5;\n}\n\n.close:hover {\n color: #000;\n text-decoration: none;\n}\n\n.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n opacity: .75;\n}\n\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n appearance: none;\n}\n\na.close.disabled {\n pointer-events: none;\n}\n\n.toast {\n max-width: 350px;\n overflow: hidden;\n font-size: 0.875rem;\n background-color: rgba(255, 255, 255, 0.85);\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(10px);\n opacity: 0;\n border-radius: 0.25rem;\n}\n\n.toast:not(:last-child) {\n margin-bottom: 0.75rem;\n}\n\n.toast.showing {\n opacity: 1;\n}\n\n.toast.show {\n display: block;\n opacity: 1;\n}\n\n.toast.hide {\n display: none;\n}\n\n.toast-header {\n display: flex;\n align-items: center;\n padding: 0.25rem 0.75rem;\n color: #6c757d;\n background-color: rgba(255, 255, 255, 0.85);\n background-clip: padding-box;\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\n.toast-body {\n padding: 0.75rem;\n}\n\n.modal-open {\n overflow: hidden;\n}\n\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.modal {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1050;\n display: none;\n width: 100%;\n height: 100%;\n overflow: hidden;\n outline: 0;\n}\n\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 0.5rem;\n pointer-events: none;\n}\n\n.modal.fade .modal-dialog {\n transition: transform 0.3s ease-out;\n transform: translate(0, -50px);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .modal.fade .modal-dialog {\n transition: none;\n }\n}\n\n.modal.show .modal-dialog {\n transform: none;\n}\n\n.modal-dialog-scrollable {\n display: flex;\n max-height: calc(100% - 1rem);\n}\n\n.modal-dialog-scrollable .modal-content {\n max-height: calc(100vh - 1rem);\n overflow: hidden;\n}\n\n.modal-dialog-scrollable .modal-header,\n.modal-dialog-scrollable .modal-footer {\n flex-shrink: 0;\n}\n\n.modal-dialog-scrollable .modal-body {\n overflow-y: auto;\n}\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - 1rem);\n}\n\n.modal-dialog-centered::before {\n display: block;\n height: calc(100vh - 1rem);\n content: \"\";\n}\n\n.modal-dialog-centered.modal-dialog-scrollable {\n flex-direction: column;\n justify-content: center;\n height: 100%;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable .modal-content {\n max-height: none;\n}\n\n.modal-dialog-centered.modal-dialog-scrollable::before {\n content: none;\n}\n\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n pointer-events: auto;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n outline: 0;\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1040;\n width: 100vw;\n height: 100vh;\n background-color: #000;\n}\n\n.modal-backdrop.fade {\n opacity: 0;\n}\n\n.modal-backdrop.show {\n opacity: 0.5;\n}\n\n.modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 1rem 1rem;\n border-bottom: 1px solid #dee2e6;\n border-top-left-radius: 0.3rem;\n border-top-right-radius: 0.3rem;\n}\n\n.modal-header .close {\n padding: 1rem 1rem;\n margin: -1rem -1rem -1rem auto;\n}\n\n.modal-title {\n margin-bottom: 0;\n line-height: 1.5;\n}\n\n.modal-body {\n position: relative;\n flex: 1 1 auto;\n padding: 1rem;\n}\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 1rem;\n border-top: 1px solid #dee2e6;\n border-bottom-right-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.modal-footer > :not(:first-child) {\n margin-left: .25rem;\n}\n\n.modal-footer > :not(:last-child) {\n margin-right: .25rem;\n}\n\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n@media (min-width: 576px) {\n .modal-dialog {\n max-width: 500px;\n margin: 1.75rem auto;\n }\n .modal-dialog-scrollable {\n max-height: calc(100% - 3.5rem);\n }\n .modal-dialog-scrollable .modal-content {\n max-height: calc(100vh - 3.5rem);\n }\n .modal-dialog-centered {\n min-height: calc(100% - 3.5rem);\n }\n .modal-dialog-centered::before {\n height: calc(100vh - 3.5rem);\n }\n .modal-sm {\n max-width: 300px;\n }\n}\n\n@media (min-width: 992px) {\n .modal-lg,\n .modal-xl {\n max-width: 800px;\n }\n}\n\n@media (min-width: 1200px) {\n .modal-xl {\n max-width: 1140px;\n }\n}\n\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n opacity: 0;\n}\n\n.tooltip.show {\n opacity: 0.9;\n}\n\n.tooltip .arrow {\n position: absolute;\n display: block;\n width: 0.8rem;\n height: 0.4rem;\n}\n\n.tooltip .arrow::before {\n position: absolute;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^=\"top\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n bottom: 0;\n}\n\n.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n top: 0;\n border-width: 0.4rem 0.4rem 0;\n border-top-color: #000;\n}\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^=\"right\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n left: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n right: 0;\n border-width: 0.4rem 0.4rem 0.4rem 0;\n border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=\"bottom\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n top: 0;\n}\n\n.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n bottom: 0;\n border-width: 0 0.4rem 0.4rem;\n border-bottom-color: #000;\n}\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^=\"left\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n right: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n left: 0;\n border-width: 0.4rem 0 0.4rem 0.4rem;\n border-left-color: #000;\n}\n\n.tooltip-inner {\n max-width: 200px;\n padding: 0.25rem 0.5rem;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 0.25rem;\n}\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: block;\n max-width: 276px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n}\n\n.popover .arrow {\n position: absolute;\n display: block;\n width: 1rem;\n height: 0.5rem;\n margin: 0 0.3rem;\n}\n\n.popover .arrow::before, .popover .arrow::after {\n position: absolute;\n display: block;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-popover-top, .bs-popover-auto[x-placement^=\"top\"] {\n margin-bottom: 0.5rem;\n}\n\n.bs-popover-top > .arrow, .bs-popover-auto[x-placement^=\"top\"] > .arrow {\n bottom: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^=\"top\"] > .arrow::before {\n bottom: 0;\n border-width: 0.5rem 0.5rem 0;\n border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^=\"top\"] > .arrow::after {\n bottom: 1px;\n border-width: 0.5rem 0.5rem 0;\n border-top-color: #fff;\n}\n\n.bs-popover-right, .bs-popover-auto[x-placement^=\"right\"] {\n margin-left: 0.5rem;\n}\n\n.bs-popover-right > .arrow, .bs-popover-auto[x-placement^=\"right\"] > .arrow {\n left: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^=\"right\"] > .arrow::before {\n left: 0;\n border-width: 0.5rem 0.5rem 0.5rem 0;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^=\"right\"] > .arrow::after {\n left: 1px;\n border-width: 0.5rem 0.5rem 0.5rem 0;\n border-right-color: #fff;\n}\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^=\"bottom\"] {\n margin-top: 0.5rem;\n}\n\n.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow {\n top: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::before {\n top: 0;\n border-width: 0 0.5rem 0.5rem 0.5rem;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^=\"bottom\"] > .arrow::after {\n top: 1px;\n border-width: 0 0.5rem 0.5rem 0.5rem;\n border-bottom-color: #fff;\n}\n\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: 1rem;\n margin-left: -0.5rem;\n content: \"\";\n border-bottom: 1px solid #f7f7f7;\n}\n\n.bs-popover-left, .bs-popover-auto[x-placement^=\"left\"] {\n margin-right: 0.5rem;\n}\n\n.bs-popover-left > .arrow, .bs-popover-auto[x-placement^=\"left\"] > .arrow {\n right: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^=\"left\"] > .arrow::before {\n right: 0;\n border-width: 0.5rem 0 0.5rem 0.5rem;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^=\"left\"] > .arrow::after {\n right: 1px;\n border-width: 0.5rem 0 0.5rem 0.5rem;\n border-left-color: #fff;\n}\n\n.popover-header {\n padding: 0.5rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-top-left-radius: calc(0.3rem - 1px);\n border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n display: none;\n}\n\n.popover-body {\n padding: 0.5rem 0.75rem;\n color: #212529;\n}\n\n.carousel {\n position: relative;\n}\n\n.carousel.pointer-event {\n touch-action: pan-y;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-inner::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.carousel-item {\n position: relative;\n display: none;\n float: left;\n width: 100%;\n margin-right: -100%;\n backface-visibility: hidden;\n transition: transform 0.6s ease-in-out;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-item {\n transition: none;\n }\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n}\n\n.carousel-item-next:not(.carousel-item-left),\n.active.carousel-item-right {\n transform: translateX(100%);\n}\n\n.carousel-item-prev:not(.carousel-item-right),\n.active.carousel-item-left {\n transform: translateX(-100%);\n}\n\n.carousel-fade .carousel-item {\n opacity: 0;\n transition-property: opacity;\n transform: none;\n}\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n z-index: 1;\n opacity: 1;\n}\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n z-index: 0;\n opacity: 0;\n transition: 0s 0.6s opacity;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-fade .active.carousel-item-left,\n .carousel-fade .active.carousel-item-right {\n transition: none;\n }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 15%;\n color: #fff;\n text-align: center;\n opacity: 0.5;\n transition: opacity 0.15s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-control-prev,\n .carousel-control-next {\n transition: none;\n }\n}\n\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n opacity: 0.9;\n}\n\n.carousel-control-prev {\n left: 0;\n}\n\n.carousel-control-next {\n right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: no-repeat 50% / 100% 100%;\n}\n\n.carousel-control-prev-icon {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\");\n}\n\n.carousel-control-next-icon {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\");\n}\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0;\n margin-right: 15%;\n margin-left: 15%;\n list-style: none;\n}\n\n.carousel-indicators li {\n box-sizing: content-box;\n flex: 0 1 auto;\n width: 30px;\n height: 3px;\n margin-right: 3px;\n margin-left: 3px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #fff;\n background-clip: padding-box;\n border-top: 10px solid transparent;\n border-bottom: 10px solid transparent;\n opacity: .5;\n transition: opacity 0.6s ease;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .carousel-indicators li {\n transition: none;\n }\n}\n\n.carousel-indicators .active {\n opacity: 1;\n}\n\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n}\n\n@keyframes spinner-border {\n to {\n transform: rotate(360deg);\n }\n}\n\n.spinner-border {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n vertical-align: text-bottom;\n border: 0.25em solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: spinner-border .75s linear infinite;\n}\n\n.spinner-border-sm {\n width: 1rem;\n height: 1rem;\n border-width: 0.2em;\n}\n\n@keyframes spinner-grow {\n 0% {\n transform: scale(0);\n }\n 50% {\n opacity: 1;\n }\n}\n\n.spinner-grow {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n vertical-align: text-bottom;\n background-color: currentColor;\n border-radius: 50%;\n opacity: 0;\n animation: spinner-grow .75s linear infinite;\n}\n\n.spinner-grow-sm {\n width: 1rem;\n height: 1rem;\n}\n\n.align-baseline {\n vertical-align: baseline !important;\n}\n\n.align-top {\n vertical-align: top !important;\n}\n\n.align-middle {\n vertical-align: middle !important;\n}\n\n.align-bottom {\n vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n vertical-align: text-top !important;\n}\n\n.bg-primary {\n background-color: #007bff !important;\n}\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n background-color: #0062cc !important;\n}\n\n.bg-secondary {\n background-color: #6c757d !important;\n}\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n background-color: #545b62 !important;\n}\n\n.bg-success {\n background-color: #28a745 !important;\n}\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n background-color: #1e7e34 !important;\n}\n\n.bg-info {\n background-color: #17a2b8 !important;\n}\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n background-color: #117a8b !important;\n}\n\n.bg-warning {\n background-color: #ffc107 !important;\n}\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n background-color: #d39e00 !important;\n}\n\n.bg-danger {\n background-color: #dc3545 !important;\n}\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n background-color: #bd2130 !important;\n}\n\n.bg-light {\n background-color: #f8f9fa !important;\n}\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n background-color: #343a40 !important;\n}\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n background-color: #1d2124 !important;\n}\n\n.bg-white {\n background-color: #fff !important;\n}\n\n.bg-transparent {\n background-color: transparent !important;\n}\n\n.border {\n border: 1px solid #dee2e6 !important;\n}\n\n.border-top {\n border-top: 1px solid #dee2e6 !important;\n}\n\n.border-right {\n border-right: 1px solid #dee2e6 !important;\n}\n\n.border-bottom {\n border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-left {\n border-left: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n border: 0 !important;\n}\n\n.border-top-0 {\n border-top: 0 !important;\n}\n\n.border-right-0 {\n border-right: 0 !important;\n}\n\n.border-bottom-0 {\n border-bottom: 0 !important;\n}\n\n.border-left-0 {\n border-left: 0 !important;\n}\n\n.border-primary {\n border-color: #007bff !important;\n}\n\n.border-secondary {\n border-color: #6c757d !important;\n}\n\n.border-success {\n border-color: #28a745 !important;\n}\n\n.border-info {\n border-color: #17a2b8 !important;\n}\n\n.border-warning {\n border-color: #ffc107 !important;\n}\n\n.border-danger {\n border-color: #dc3545 !important;\n}\n\n.border-light {\n border-color: #f8f9fa !important;\n}\n\n.border-dark {\n border-color: #343a40 !important;\n}\n\n.border-white {\n border-color: #fff !important;\n}\n\n.rounded-sm {\n border-radius: 0.2rem !important;\n}\n\n.rounded {\n border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n border-top-left-radius: 0.25rem !important;\n border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n border-top-right-radius: 0.25rem !important;\n border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n border-bottom-right-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n border-top-left-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-lg {\n border-radius: 0.3rem !important;\n}\n\n.rounded-circle {\n border-radius: 50% !important;\n}\n\n.rounded-pill {\n border-radius: 50rem !important;\n}\n\n.rounded-0 {\n border-radius: 0 !important;\n}\n\n.clearfix::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n}\n\n.embed-responsive::before {\n display: block;\n content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n\n.embed-responsive-21by9::before {\n padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n padding-top: 100%;\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.float-left {\n float: left !important;\n}\n\n.float-right {\n float: right !important;\n}\n\n.float-none {\n float: none !important;\n}\n\n@media (min-width: 576px) {\n .float-sm-left {\n float: left !important;\n }\n .float-sm-right {\n float: right !important;\n }\n .float-sm-none {\n float: none !important;\n }\n}\n\n@media (min-width: 768px) {\n .float-md-left {\n float: left !important;\n }\n .float-md-right {\n float: right !important;\n }\n .float-md-none {\n float: none !important;\n }\n}\n\n@media (min-width: 992px) {\n .float-lg-left {\n float: left !important;\n }\n .float-lg-right {\n float: right !important;\n }\n .float-lg-none {\n float: none !important;\n }\n}\n\n@media (min-width: 1200px) {\n .float-xl-left {\n float: left !important;\n }\n .float-xl-right {\n float: right !important;\n }\n .float-xl-none {\n float: none !important;\n }\n}\n\n.overflow-auto {\n overflow: auto !important;\n}\n\n.overflow-hidden {\n overflow: hidden !important;\n}\n\n.position-static {\n position: static !important;\n}\n\n.position-relative {\n position: relative !important;\n}\n\n.position-absolute {\n position: absolute !important;\n}\n\n.position-fixed {\n position: fixed !important;\n}\n\n.position-sticky {\n position: sticky !important;\n}\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1030;\n}\n\n@supports (position: sticky) {\n .sticky-top {\n position: sticky;\n top: 0;\n z-index: 1020;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal;\n}\n\n.shadow-sm {\n box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow {\n box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-lg {\n box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n box-shadow: none !important;\n}\n\n.w-25 {\n width: 25% !important;\n}\n\n.w-50 {\n width: 50% !important;\n}\n\n.w-75 {\n width: 75% !important;\n}\n\n.w-100 {\n width: 100% !important;\n}\n\n.w-auto {\n width: auto !important;\n}\n\n.h-25 {\n height: 25% !important;\n}\n\n.h-50 {\n height: 50% !important;\n}\n\n.h-75 {\n height: 75% !important;\n}\n\n.h-100 {\n height: 100% !important;\n}\n\n.h-auto {\n height: auto !important;\n}\n\n.mw-100 {\n max-width: 100% !important;\n}\n\n.mh-100 {\n max-height: 100% !important;\n}\n\n.min-vw-100 {\n min-width: 100vw !important;\n}\n\n.min-vh-100 {\n min-height: 100vh !important;\n}\n\n.vw-100 {\n width: 100vw !important;\n}\n\n.vh-100 {\n height: 100vh !important;\n}\n\n.stretched-link::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1;\n pointer-events: auto;\n content: \"\";\n background-color: rgba(0, 0, 0, 0);\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n.text-monospace {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !important;\n}\n\n.text-justify {\n text-align: justify !important;\n}\n\n.text-wrap {\n white-space: normal !important;\n}\n\n.text-nowrap {\n white-space: nowrap !important;\n}\n\n.text-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.text-left {\n text-align: left !important;\n}\n\n.text-right {\n text-align: right !important;\n}\n\n.text-center {\n text-align: center !important;\n}\n\n@media (min-width: 576px) {\n .text-sm-left {\n text-align: left !important;\n }\n .text-sm-right {\n text-align: right !important;\n }\n .text-sm-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 768px) {\n .text-md-left {\n text-align: left !important;\n }\n .text-md-right {\n text-align: right !important;\n }\n .text-md-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 992px) {\n .text-lg-left {\n text-align: left !important;\n }\n .text-lg-right {\n text-align: right !important;\n }\n .text-lg-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 1200px) {\n .text-xl-left {\n text-align: left !important;\n }\n .text-xl-right {\n text-align: right !important;\n }\n .text-xl-center {\n text-align: center !important;\n }\n}\n\n.text-lowercase {\n text-transform: lowercase !important;\n}\n\n.text-uppercase {\n text-transform: uppercase !important;\n}\n\n.text-capitalize {\n text-transform: capitalize !important;\n}\n\n.font-weight-light {\n font-weight: 300 !important;\n}\n\n.font-weight-lighter {\n font-weight: lighter !important;\n}\n\n.font-weight-normal {\n font-weight: 400 !important;\n}\n\n.font-weight-bold {\n font-weight: 700 !important;\n}\n\n.font-weight-bolder {\n font-weight: bolder !important;\n}\n\n.font-italic {\n font-style: italic !important;\n}\n\n.text-white {\n color: #fff !important;\n}\n\n.text-primary {\n color: #007bff !important;\n}\n\na.text-primary:hover, a.text-primary:focus {\n color: #0056b3 !important;\n}\n\n.text-secondary {\n color: #6c757d !important;\n}\n\na.text-secondary:hover, a.text-secondary:focus {\n color: #494f54 !important;\n}\n\n.text-success {\n color: #28a745 !important;\n}\n\na.text-success:hover, a.text-success:focus {\n color: #19692c !important;\n}\n\n.text-info {\n color: #17a2b8 !important;\n}\n\na.text-info:hover, a.text-info:focus {\n color: #0f6674 !important;\n}\n\n.text-warning {\n color: #ffc107 !important;\n}\n\na.text-warning:hover, a.text-warning:focus {\n color: #ba8b00 !important;\n}\n\n.text-danger {\n color: #dc3545 !important;\n}\n\na.text-danger:hover, a.text-danger:focus {\n color: #a71d2a !important;\n}\n\n.text-light {\n color: #f8f9fa !important;\n}\n\na.text-light:hover, a.text-light:focus {\n color: #cbd3da !important;\n}\n\n.text-dark {\n color: #343a40 !important;\n}\n\na.text-dark:hover, a.text-dark:focus {\n color: #121416 !important;\n}\n\n.text-body {\n color: #212529 !important;\n}\n\n.text-muted {\n color: #6c757d !important;\n}\n\n.text-black-50 {\n color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n.text-decoration-none {\n text-decoration: none !important;\n}\n\n.text-break {\n word-break: break-word !important;\n overflow-wrap: break-word !important;\n}\n\n.text-reset {\n color: inherit !important;\n}\n\n.visible {\n visibility: visible !important;\n}\n\n.invisible {\n visibility: hidden !important;\n}\n\n@media print {\n *,\n *::before,\n *::after {\n text-shadow: none !important;\n box-shadow: none !important;\n }\n a:not(.btn) {\n text-decoration: underline;\n }\n abbr[title]::after {\n content: \" (\" attr(title) \")\";\n }\n pre {\n white-space: pre-wrap !important;\n }\n pre,\n blockquote {\n border: 1px solid #adb5bd;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n @page {\n size: a3;\n }\n body {\n min-width: 992px !important;\n }\n .container {\n min-width: 992px !important;\n }\n .navbar {\n display: none;\n }\n .badge {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6 !important;\n }\n .table-dark {\n color: inherit;\n }\n .table-dark th,\n .table-dark td,\n .table-dark thead th,\n .table-dark tbody + tbody {\n border-color: #dee2e6;\n }\n .table .thead-dark th {\n color: inherit;\n border-color: #dee2e6;\n }\n}\n\n/*# sourceMappingURL=bootstrap.css.map */",":root {\n // Custom variable values only support SassScript inside `#{}`.\n @each $color, $value in $colors {\n --#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$color}: #{$value};\n }\n\n @each $bp, $value in $grid-breakpoints {\n --breakpoint-#{$bp}: #{$value};\n }\n\n // Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --font-family-sans-serif: #{inspect($font-family-sans-serif)};\n --font-family-monospace: #{inspect($font-family-monospace)};\n}\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `<th>` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `<p>`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `<td>` alignment by inheriting from the `<body>`, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `<div>`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `<body>` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n","// stylelint-disable declaration-no-important, selector-list-comma-newline-after\n\n//\n// Headings\n//\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1, .h1 { @include font-size($h1-font-size); }\nh2, .h2 { @include font-size($h2-font-size); }\nh3, .h3 { @include font-size($h3-font-size); }\nh4, .h4 { @include font-size($h4-font-size); }\nh5, .h5 { @include font-size($h5-font-size); }\nh6, .h6 { @include font-size($h6-font-size); }\n\n.lead {\n @include font-size($lead-font-size);\n font-weight: $lead-font-weight;\n}\n\n// Type display classes\n.display-1 {\n @include font-size($display1-size);\n font-weight: $display1-weight;\n line-height: $display-line-height;\n}\n.display-2 {\n @include font-size($display2-size);\n font-weight: $display2-weight;\n line-height: $display-line-height;\n}\n.display-3 {\n @include font-size($display3-size);\n font-weight: $display3-weight;\n line-height: $display-line-height;\n}\n.display-4 {\n @include font-size($display4-size);\n font-weight: $display4-weight;\n line-height: $display-line-height;\n}\n\n\n//\n// Horizontal rules\n//\n\nhr {\n margin-top: $hr-margin-y;\n margin-bottom: $hr-margin-y;\n border: 0;\n border-top: $hr-border-width solid $hr-border-color;\n}\n\n\n//\n// Emphasis\n//\n\nsmall,\n.small {\n @include font-size($small-font-size);\n font-weight: $font-weight-normal;\n}\n\nmark,\n.mark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n//\n// Lists\n//\n\n.list-unstyled {\n @include list-unstyled;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n @include list-unstyled;\n}\n.list-inline-item {\n display: inline-block;\n\n &:not(:last-child) {\n margin-right: $list-inline-padding;\n }\n}\n\n\n//\n// Misc\n//\n\n// Builds on `abbr`\n.initialism {\n @include font-size(90%);\n text-transform: uppercase;\n}\n\n// Blockquotes\n.blockquote {\n margin-bottom: $spacer;\n @include font-size($blockquote-font-size);\n}\n\n.blockquote-footer {\n display: block;\n @include font-size($blockquote-small-font-size);\n color: $blockquote-small-color;\n\n &::before {\n content: \"\\2014\\00A0\"; // em dash, nbsp\n }\n}\n","// Lists\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n@mixin list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n","// Responsive images (ensure images don't scale beyond their parents)\n//\n// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.\n// We previously tried the \"images are responsive by default\" approach in Bootstrap v2,\n// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)\n// which weren't expecting the images within themselves to be involuntarily resized.\n// See also https://github.com/twbs/bootstrap/issues/18178\n.img-fluid {\n @include img-fluid;\n}\n\n\n// Image thumbnails\n.img-thumbnail {\n padding: $thumbnail-padding;\n background-color: $thumbnail-bg;\n border: $thumbnail-border-width solid $thumbnail-border-color;\n @include border-radius($thumbnail-border-radius);\n @include box-shadow($thumbnail-box-shadow);\n\n // Keep them at most 100% wide\n @include img-fluid;\n}\n\n//\n// Figures\n//\n\n.figure {\n // Ensures the caption's text aligns with the image.\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: $spacer / 2;\n line-height: 1;\n}\n\n.figure-caption {\n @include font-size($figure-caption-font-size);\n color: $figure-caption-color;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n@mixin img-fluid {\n // Part 1: Set a maximum relative to the parent\n max-width: 100%;\n // Part 2: Override the height to auto, otherwise images will be stretched\n // when setting a width and height attribute on the img element.\n height: auto;\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size.\n\n@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {\n background-image: url($file-1x);\n\n // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,\n // but doesn't convert dppx=>dpi.\n // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.\n // Compatibility info: https://caniuse.com/#feat=css-media-resolution\n @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx\n only screen and (min-resolution: 2dppx) { // Standardized\n background-image: url($file-2x);\n background-size: $width-1x $height-1x;\n }\n @include deprecate(\"`img-retina()`\", \"v4.3.0\", \"v5\");\n}\n","// stylelint-disable property-blacklist\n// Single side border-radius\n\n@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {\n @if $enable-rounded {\n border-radius: $radius;\n }\n @else if $fallback-border-radius != false {\n border-radius: $fallback-border-radius;\n }\n}\n\n@mixin border-top-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-top-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n }\n}\n\n@mixin border-top-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-right-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-left-radius($radius) {\n @if $enable-rounded {\n border-bottom-left-radius: $radius;\n }\n}\n","// Inline code\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-break: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n @include box-shadow($kbd-box-shadow);\n\n kbd {\n padding: 0;\n @include font-size(100%);\n font-weight: $nested-kbd-font-weight;\n @include box-shadow(none);\n }\n}\n\n// Blocks of code\npre {\n display: block;\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: $pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","//\n// Basic Bootstrap table\n//\n\n.table {\n width: 100%;\n margin-bottom: $spacer;\n color: $table-color;\n background-color: $table-bg; // Reset for nesting within parents with `background-color`.\n\n th,\n td {\n padding: $table-cell-padding;\n vertical-align: top;\n border-top: $table-border-width solid $table-border-color;\n }\n\n thead th {\n vertical-align: bottom;\n border-bottom: (2 * $table-border-width) solid $table-border-color;\n }\n\n tbody + tbody {\n border-top: (2 * $table-border-width) solid $table-border-color;\n }\n}\n\n\n//\n// Condensed table w/ half padding\n//\n\n.table-sm {\n th,\n td {\n padding: $table-cell-padding-sm;\n }\n}\n\n\n// Border versions\n//\n// Add or remove borders all around the table and between all the columns.\n\n.table-bordered {\n border: $table-border-width solid $table-border-color;\n\n th,\n td {\n border: $table-border-width solid $table-border-color;\n }\n\n thead {\n th,\n td {\n border-bottom-width: 2 * $table-border-width;\n }\n }\n}\n\n.table-borderless {\n th,\n td,\n thead th,\n tbody + tbody {\n border: 0;\n }\n}\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n tbody tr:nth-of-type(#{$table-striped-order}) {\n background-color: $table-accent-bg;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n tbody tr {\n @include hover {\n color: $table-hover-color;\n background-color: $table-hover-bg;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n@each $color, $value in $theme-colors {\n @include table-row-variant($color, theme-color-level($color, $table-bg-level), theme-color-level($color, $table-border-level));\n}\n\n@include table-row-variant(active, $table-active-bg);\n\n\n// Dark styles\n//\n// Same table markup, but inverted color scheme: dark background and light text.\n\n// stylelint-disable-next-line no-duplicate-selectors\n.table {\n .thead-dark {\n th {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n border-color: $table-dark-border-color;\n }\n }\n\n .thead-light {\n th {\n color: $table-head-color;\n background-color: $table-head-bg;\n border-color: $table-border-color;\n }\n }\n}\n\n.table-dark {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n\n th,\n td,\n thead th {\n border-color: $table-dark-border-color;\n }\n\n &.table-bordered {\n border: 0;\n }\n\n &.table-striped {\n tbody tr:nth-of-type(odd) {\n background-color: $table-dark-accent-bg;\n }\n }\n\n &.table-hover {\n tbody tr {\n @include hover {\n color: $table-dark-hover-color;\n background-color: $table-dark-hover-bg;\n }\n }\n }\n}\n\n\n// Responsive tables\n//\n// Generate series of `.table-responsive-*` classes for configuring the screen\n// size of where your table will overflow.\n\n.table-responsive {\n @each $breakpoint in map-keys($grid-breakpoints) {\n $next: breakpoint-next($breakpoint, $grid-breakpoints);\n $infix: breakpoint-infix($next, $grid-breakpoints);\n\n &#{$infix} {\n @include media-breakpoint-down($breakpoint) {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n\n // Prevent double border on horizontal scroll due to use of `display: block;`\n > .table-bordered {\n border: 0;\n }\n }\n }\n }\n}\n","// Tables\n\n@mixin table-row-variant($state, $background, $border: null) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table-#{$state} {\n &,\n > th,\n > td {\n background-color: $background;\n }\n\n @if $border != null {\n th,\n td,\n thead th,\n tbody + tbody {\n border-color: $border;\n }\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover {\n $hover-background: darken($background, 5%);\n\n .table-#{$state} {\n @include hover {\n background-color: $hover-background;\n\n > td,\n > th {\n background-color: $hover-background;\n }\n }\n }\n }\n}\n","// Bootstrap functions\n//\n// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.\n\n// Ascending\n// Used to evaluate Sass maps like our grid breakpoints.\n@mixin _assert-ascending($map, $map-name) {\n $prev-key: null;\n $prev-num: null;\n @each $key, $num in $map {\n @if $prev-num == null or unit($num) == \"%\" {\n // Do nothing\n } @else if not comparable($prev-num, $num) {\n @warn \"Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n } @else if $prev-num >= $num {\n @warn \"Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n }\n $prev-key: $key;\n $prev-num: $num;\n }\n}\n\n// Starts at zero\n// Used to ensure the min-width of the lowest breakpoint starts at 0.\n@mixin _assert-starts-at-zero($map, $map-name: \"$grid-breakpoints\") {\n $values: map-values($map);\n $first-value: nth($values, 1);\n @if $first-value != 0 {\n @warn \"First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.\";\n }\n}\n\n// Replace `$search` with `$replace` in `$string`\n// Used on our SVG icon backgrounds for custom forms.\n//\n// @author Hugo Giraudel\n// @param {String} $string - Initial string\n// @param {String} $search - Substring to replace\n// @param {String} $replace ('') - New value\n// @return {String} - Updated string\n@function str-replace($string, $search, $replace: \"\") {\n $index: str-index($string, $search);\n\n @if $index {\n @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);\n }\n\n @return $string;\n}\n\n// Color contrast\n@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) {\n $r: red($color);\n $g: green($color);\n $b: blue($color);\n\n $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;\n\n @if ($yiq >= $yiq-contrasted-threshold) {\n @return $dark;\n } @else {\n @return $light;\n }\n}\n\n// Retrieve color Sass maps\n@function color($key: \"blue\") {\n @return map-get($colors, $key);\n}\n\n@function theme-color($key: \"primary\") {\n @return map-get($theme-colors, $key);\n}\n\n@function gray($key: \"100\") {\n @return map-get($grays, $key);\n}\n\n// Request a theme color level\n@function theme-color-level($color-name: \"primary\", $level: 0) {\n $color: theme-color($color-name);\n $color-base: if($level > 0, $black, $white);\n $level: abs($level);\n\n @return mix($color-base, $color, $level * $theme-color-interval);\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Textual form controls\n//\n\n.form-control {\n display: block;\n width: 100%;\n height: $input-height;\n padding: $input-padding-y $input-padding-x;\n font-family: $input-font-family;\n @include font-size($input-font-size);\n font-weight: $input-font-weight;\n line-height: $input-line-height;\n color: $input-color;\n background-color: $input-bg;\n background-clip: padding-box;\n border: $input-border-width solid $input-border-color;\n\n // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.\n @include border-radius($input-border-radius, 0);\n\n @include box-shadow($input-box-shadow);\n @include transition($input-transition);\n\n // Unstyle the caret on `<select>`s in IE10+.\n &::-ms-expand {\n background-color: transparent;\n border: 0;\n }\n\n // Customize the `:focus` state to imitate native WebKit styles.\n @include form-control-focus();\n\n // Placeholder\n &::placeholder {\n color: $input-placeholder-color;\n // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.\n opacity: 1;\n }\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &:disabled,\n &[readonly] {\n background-color: $input-disabled-bg;\n // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.\n opacity: 1;\n }\n}\n\nselect.form-control {\n &:focus::-ms-value {\n // Suppress the nested default white text on blue background highlight given to\n // the selected option text when the (still closed) <select> receives focus\n // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to\n // match the appearance of the native widget.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n}\n\n// Make file inputs better match text inputs by forcing them to new lines.\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n\n//\n// Labels\n//\n\n// For use with horizontal and inline forms, when you need the label (or legend)\n// text to align with the form controls.\n.col-form-label {\n padding-top: calc(#{$input-padding-y} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});\n margin-bottom: 0; // Override the `<label>/<legend>` default\n @include font-size(inherit); // Override the `<legend>` default\n line-height: $input-line-height;\n}\n\n.col-form-label-lg {\n padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width});\n @include font-size($input-font-size-lg);\n line-height: $input-line-height-lg;\n}\n\n.col-form-label-sm {\n padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width});\n @include font-size($input-font-size-sm);\n line-height: $input-line-height-sm;\n}\n\n\n// Readonly controls as plain text\n//\n// Apply class to a readonly input to make it appear like regular plain\n// text (without any border, background color, focus indicator)\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: $input-padding-y;\n padding-bottom: $input-padding-y;\n margin-bottom: 0; // match inputs if this class comes on inputs with default margins\n line-height: $input-line-height;\n color: $input-plaintext-color;\n background-color: transparent;\n border: solid transparent;\n border-width: $input-border-width 0;\n\n &.form-control-sm,\n &.form-control-lg {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n//\n// Repeated in `_input_group.scss` to avoid Sass extend issues.\n\n.form-control-sm {\n height: $input-height-sm;\n padding: $input-padding-y-sm $input-padding-x-sm;\n @include font-size($input-font-size-sm);\n line-height: $input-line-height-sm;\n @include border-radius($input-border-radius-sm);\n}\n\n.form-control-lg {\n height: $input-height-lg;\n padding: $input-padding-y-lg $input-padding-x-lg;\n @include font-size($input-font-size-lg);\n line-height: $input-line-height-lg;\n @include border-radius($input-border-radius-lg);\n}\n\n// stylelint-disable-next-line no-duplicate-selectors\nselect.form-control {\n &[size],\n &[multiple] {\n height: auto;\n }\n}\n\ntextarea.form-control {\n height: auto;\n}\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: $form-group-margin-bottom;\n}\n\n.form-text {\n display: block;\n margin-top: $form-text-margin-top;\n}\n\n\n// Form grid\n//\n// Special replacement for our grid system's `.row` for tighter form layouts.\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$form-grid-gutter-width / 2;\n margin-left: -$form-grid-gutter-width / 2;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: $form-grid-gutter-width / 2;\n padding-left: $form-grid-gutter-width / 2;\n }\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.form-check {\n position: relative;\n display: block;\n padding-left: $form-check-input-gutter;\n}\n\n.form-check-input {\n position: absolute;\n margin-top: $form-check-input-margin-y;\n margin-left: -$form-check-input-gutter;\n\n &:disabled ~ .form-check-label {\n color: $text-muted;\n }\n}\n\n.form-check-label {\n margin-bottom: 0; // Override default `<label>` bottom margin\n}\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0; // Override base .form-check\n margin-right: $form-check-inline-margin-x;\n\n // Undo .form-check-input defaults and add some `margin-right`.\n .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: $form-check-inline-input-margin-x;\n margin-left: 0;\n }\n}\n\n\n// Form validation\n//\n// Provide feedback to users when form field values are valid or invalid. Works\n// primarily for client-side validation via scoped `:invalid` and `:valid`\n// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for\n// server side validation.\n\n@each $state, $data in $form-validation-states {\n @include form-validation-state($state, map-get($data, color), map-get($data, icon));\n}\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height)\n\n // Because we use flex, the initial sizing of checkboxes is collapsed and\n // doesn't occupy the full-width (which is what we want for xs grid tier),\n // so we force that here.\n .form-check {\n width: 100%;\n }\n\n // Kick in the inline\n @include media-breakpoint-up(sm) {\n label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0;\n }\n\n // Inline-block all the things for \"inline\"\n .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0;\n }\n\n // Allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n // Make static controls behave like regular ones\n .form-control-plaintext {\n display: inline-block;\n }\n\n .input-group,\n .custom-select {\n width: auto;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match.\n .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0;\n }\n .form-check-input {\n position: relative;\n flex-shrink: 0;\n margin-top: 0;\n margin-right: $form-check-input-margin-x;\n margin-left: 0;\n }\n\n .custom-control {\n align-items: center;\n justify-content: center;\n }\n .custom-control-label {\n margin-bottom: 0;\n }\n }\n}\n","// stylelint-disable property-blacklist\n@mixin transition($transition...) {\n @if $enable-transitions {\n @if length($transition) == 0 {\n transition: $transition-base;\n } @else {\n transition: $transition;\n }\n }\n\n @if $enable-prefers-reduced-motion-media-query {\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n }\n}\n","// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `$input-focus-border-color` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n@mixin form-control-focus() {\n &:focus {\n color: $input-focus-color;\n background-color: $input-focus-bg;\n border-color: $input-focus-border-color;\n outline: 0;\n // Avoid using mixin so we can pass custom focus shadow properly\n @if $enable-shadows {\n box-shadow: $input-box-shadow, $input-focus-box-shadow;\n } @else {\n box-shadow: $input-focus-box-shadow;\n }\n }\n}\n\n\n@mixin form-validation-state($state, $color, $icon) {\n .#{$state}-feedback {\n display: none;\n width: 100%;\n margin-top: $form-feedback-margin-top;\n @include font-size($form-feedback-font-size);\n color: $color;\n }\n\n .#{$state}-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%; // Contain to parent when possible\n padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;\n margin-top: .1rem;\n @include font-size($form-feedback-tooltip-font-size);\n line-height: $form-feedback-tooltip-line-height;\n color: color-yiq($color);\n background-color: rgba($color, $form-feedback-tooltip-opacity);\n @include border-radius($form-feedback-tooltip-border-radius);\n }\n\n .form-control {\n .was-validated &:#{$state},\n &.is-#{$state} {\n border-color: $color;\n\n @if $enable-validation-icons {\n padding-right: $input-height-inner;\n background-image: $icon;\n background-repeat: no-repeat;\n background-position: center right $input-height-inner-quarter;\n background-size: $input-height-inner-half $input-height-inner-half;\n }\n\n &:focus {\n border-color: $color;\n box-shadow: 0 0 0 $input-focus-width rgba($color, .25);\n }\n\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n }\n }\n\n // stylelint-disable-next-line selector-no-qualifying-type\n textarea.form-control {\n .was-validated &:#{$state},\n &.is-#{$state} {\n @if $enable-validation-icons {\n padding-right: $input-height-inner;\n background-position: top $input-height-inner-quarter right $input-height-inner-quarter;\n }\n }\n }\n\n .custom-select {\n .was-validated &:#{$state},\n &.is-#{$state} {\n border-color: $color;\n\n @if $enable-validation-icons {\n padding-right: $custom-select-feedback-icon-padding-right;\n background: $custom-select-background, $icon $custom-select-bg no-repeat $custom-select-feedback-icon-position / $custom-select-feedback-icon-size;\n }\n\n &:focus {\n border-color: $color;\n box-shadow: 0 0 0 $input-focus-width rgba($color, .25);\n }\n\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n }\n }\n\n\n .form-control-file {\n .was-validated &:#{$state},\n &.is-#{$state} {\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n }\n }\n\n .form-check-input {\n .was-validated &:#{$state},\n &.is-#{$state} {\n ~ .form-check-label {\n color: $color;\n }\n\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n }\n }\n\n .custom-control-input {\n .was-validated &:#{$state},\n &.is-#{$state} {\n ~ .custom-control-label {\n color: $color;\n\n &::before {\n border-color: $color;\n }\n }\n\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n\n &:checked {\n ~ .custom-control-label::before {\n border-color: lighten($color, 10%);\n @include gradient-bg(lighten($color, 10%));\n }\n }\n\n &:focus {\n ~ .custom-control-label::before {\n box-shadow: 0 0 0 $input-focus-width rgba($color, .25);\n }\n\n &:not(:checked) ~ .custom-control-label::before {\n border-color: $color;\n }\n }\n }\n }\n\n // custom file\n .custom-file-input {\n .was-validated &:#{$state},\n &.is-#{$state} {\n ~ .custom-file-label {\n border-color: $color;\n }\n\n ~ .#{$state}-feedback,\n ~ .#{$state}-tooltip {\n display: block;\n }\n\n &:focus {\n ~ .custom-file-label {\n border-color: $color;\n box-shadow: 0 0 0 $input-focus-width rgba($color, .25);\n }\n }\n }\n }\n}\n","// Gradients\n\n@mixin gradient-bg($color) {\n @if $enable-gradients {\n background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x;\n } @else {\n background-color: $color;\n }\n}\n\n// Horizontal gradient, from left to right\n//\n// Creates two color stops, start and end, by specifying a color and position for each color stop.\n@mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {\n background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);\n background-repeat: repeat-x;\n}\n\n// Vertical gradient, from top to bottom\n//\n// Creates two color stops, start and end, by specifying a color and position for each color stop.\n@mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {\n background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);\n background-repeat: repeat-x;\n}\n\n@mixin gradient-directional($start-color: $gray-700, $end-color: $gray-800, $deg: 45deg) {\n background-image: linear-gradient($deg, $start-color, $end-color);\n background-repeat: repeat-x;\n}\n@mixin gradient-x-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {\n background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);\n background-repeat: no-repeat;\n}\n@mixin gradient-y-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {\n background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);\n background-repeat: no-repeat;\n}\n@mixin gradient-radial($inner-color: $gray-700, $outer-color: $gray-800) {\n background-image: radial-gradient(circle, $inner-color, $outer-color);\n background-repeat: no-repeat;\n}\n@mixin gradient-striped($color: rgba($white, .15), $angle: 45deg) {\n background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Base styles\n//\n\n.btn {\n display: inline-block;\n font-family: $btn-font-family;\n font-weight: $btn-font-weight;\n color: $body-color;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n background-color: transparent;\n border: $btn-border-width solid transparent;\n @include button-size($btn-padding-y, $btn-padding-x, $btn-font-size, $btn-line-height, $btn-border-radius);\n @include transition($btn-transition);\n\n @include hover {\n color: $body-color;\n text-decoration: none;\n }\n\n &:focus,\n &.focus {\n outline: 0;\n box-shadow: $btn-focus-box-shadow;\n }\n\n // Disabled comes first so active can properly restyle\n &.disabled,\n &:disabled {\n opacity: $btn-disabled-opacity;\n @include box-shadow(none);\n }\n\n &:not(:disabled):not(.disabled):active,\n &:not(:disabled):not(.disabled).active {\n @include box-shadow($btn-active-box-shadow);\n\n &:focus {\n @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);\n }\n }\n}\n\n// Future-proof disabling of clicks on `<a>` elements\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none;\n}\n\n\n//\n// Alternate buttons\n//\n\n@each $color, $value in $theme-colors {\n .btn-#{$color} {\n @include button-variant($value, $value);\n }\n}\n\n@each $color, $value in $theme-colors {\n .btn-outline-#{$color} {\n @include button-outline-variant($value);\n }\n}\n\n\n//\n// Link buttons\n//\n\n// Make a button look and behave like a link\n.btn-link {\n font-weight: $font-weight-normal;\n color: $link-color;\n text-decoration: $link-decoration;\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n\n &:focus,\n &.focus {\n text-decoration: $link-hover-decoration;\n box-shadow: none;\n }\n\n &:disabled,\n &.disabled {\n color: $btn-link-disabled-color;\n pointer-events: none;\n }\n\n // No need for an active state here\n}\n\n\n//\n// Button Sizes\n//\n\n.btn-lg {\n @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-line-height-lg, $btn-border-radius-lg);\n}\n\n.btn-sm {\n @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-line-height-sm, $btn-border-radius-sm);\n}\n\n\n//\n// Block button\n//\n\n.btn-block {\n display: block;\n width: 100%;\n\n // Vertically space out multiple block buttons\n + .btn-block {\n margin-top: $btn-block-spacing-y;\n }\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n@mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) {\n color: color-yiq($background);\n @include gradient-bg($background);\n border-color: $border;\n @include box-shadow($btn-box-shadow);\n\n @include hover {\n color: color-yiq($hover-background);\n @include gradient-bg($hover-background);\n border-color: $hover-border;\n }\n\n &:focus,\n &.focus {\n // Avoid using mixin so we can pass custom focus shadow properly\n @if $enable-shadows {\n box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);\n } @else {\n box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);\n }\n }\n\n // Disabled comes first so active can properly restyle\n &.disabled,\n &:disabled {\n color: color-yiq($background);\n background-color: $background;\n border-color: $border;\n // Remove CSS gradients if they're enabled\n @if $enable-gradients {\n background-image: none;\n }\n }\n\n &:not(:disabled):not(.disabled):active,\n &:not(:disabled):not(.disabled).active,\n .show > &.dropdown-toggle {\n color: color-yiq($active-background);\n background-color: $active-background;\n @if $enable-gradients {\n background-image: none; // Remove the gradient for the pressed/active state\n }\n border-color: $active-border;\n\n &:focus {\n // Avoid using mixin so we can pass custom focus shadow properly\n @if $enable-shadows and $btn-active-box-shadow != none {\n box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);\n } @else {\n box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);\n }\n }\n }\n}\n\n@mixin button-outline-variant($color, $color-hover: color-yiq($color), $active-background: $color, $active-border: $color) {\n color: $color;\n border-color: $color;\n\n @include hover {\n color: $color-hover;\n background-color: $active-background;\n border-color: $active-border;\n }\n\n &:focus,\n &.focus {\n box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);\n }\n\n &.disabled,\n &:disabled {\n color: $color;\n background-color: transparent;\n }\n\n &:not(:disabled):not(.disabled):active,\n &:not(:disabled):not(.disabled).active,\n .show > &.dropdown-toggle {\n color: color-yiq($active-background);\n background-color: $active-background;\n border-color: $active-border;\n\n &:focus {\n // Avoid using mixin so we can pass custom focus shadow properly\n @if $enable-shadows and $btn-active-box-shadow != none {\n box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5);\n } @else {\n box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);\n }\n }\n }\n}\n\n// Button sizes\n@mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {\n padding: $padding-y $padding-x;\n @include font-size($font-size);\n line-height: $line-height;\n // Manually declare to provide an override to the browser default\n @include border-radius($border-radius, 0);\n}\n",".fade {\n @include transition($transition-fade);\n\n &:not(.show) {\n opacity: 0;\n }\n}\n\n.collapse {\n &:not(.show) {\n display: none;\n }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n @include transition($transition-collapse);\n}\n","// The dropdown wrapper (`<div>`)\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle {\n white-space: nowrap;\n\n // Generate the caret automatically\n @include caret;\n}\n\n// The dropdown menu\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: $zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: $dropdown-min-width;\n padding: $dropdown-padding-y 0;\n margin: $dropdown-spacer 0 0; // override default ul\n @include font-size($dropdown-font-size);\n color: $dropdown-color;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n list-style: none;\n background-color: $dropdown-bg;\n background-clip: padding-box;\n border: $dropdown-border-width solid $dropdown-border-color;\n @include border-radius($dropdown-border-radius);\n @include box-shadow($dropdown-box-shadow);\n}\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .dropdown-menu#{$infix}-left {\n right: auto;\n left: 0;\n }\n\n .dropdown-menu#{$infix}-right {\n right: 0;\n left: auto;\n }\n }\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n// Just add .dropup after the standard .dropdown class and you're set.\n.dropup {\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: $dropdown-spacer;\n }\n\n .dropdown-toggle {\n @include caret(up);\n }\n}\n\n.dropright {\n .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: $dropdown-spacer;\n }\n\n .dropdown-toggle {\n @include caret(right);\n &::after {\n vertical-align: 0;\n }\n }\n}\n\n.dropleft {\n .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: $dropdown-spacer;\n }\n\n .dropdown-toggle {\n @include caret(left);\n &::before {\n vertical-align: 0;\n }\n }\n}\n\n// When enabled Popper.js, reset basic dropdown position\n// stylelint-disable-next-line no-duplicate-selectors\n.dropdown-menu {\n &[x-placement^=\"top\"],\n &[x-placement^=\"right\"],\n &[x-placement^=\"bottom\"],\n &[x-placement^=\"left\"] {\n right: auto;\n bottom: auto;\n }\n}\n\n// Dividers (basically an `<hr>`) within the dropdown\n.dropdown-divider {\n @include nav-divider($dropdown-divider-bg, $dropdown-divider-margin-y);\n}\n\n// Links, buttons, and more within the dropdown menu\n//\n// `<button>`-specific styles are denoted with `// For <button>s`\n.dropdown-item {\n display: block;\n width: 100%; // For `<button>`s\n padding: $dropdown-item-padding-y $dropdown-item-padding-x;\n clear: both;\n font-weight: $font-weight-normal;\n color: $dropdown-link-color;\n text-align: inherit; // For `<button>`s\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n background-color: transparent; // For `<button>`s\n border: 0; // For `<button>`s\n\n // Prevent dropdown overflow if there's no padding\n // See https://github.com/twbs/bootstrap/pull/27703\n @if $dropdown-padding-y == 0 {\n &:first-child {\n @include border-top-radius($dropdown-inner-border-radius);\n }\n\n &:last-child {\n @include border-bottom-radius($dropdown-inner-border-radius);\n }\n }\n\n @include hover-focus {\n color: $dropdown-link-hover-color;\n text-decoration: none;\n @include gradient-bg($dropdown-link-hover-bg);\n }\n\n &.active,\n &:active {\n color: $dropdown-link-active-color;\n text-decoration: none;\n @include gradient-bg($dropdown-link-active-bg);\n }\n\n &.disabled,\n &:disabled {\n color: $dropdown-link-disabled-color;\n pointer-events: none;\n background-color: transparent;\n // Remove CSS gradients if they're enabled\n @if $enable-gradients {\n background-image: none;\n }\n }\n}\n\n.dropdown-menu.show {\n display: block;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: $dropdown-padding-y $dropdown-item-padding-x;\n margin-bottom: 0; // for use with heading elements\n @include font-size($font-size-sm);\n color: $dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Dropdown text\n.dropdown-item-text {\n display: block;\n padding: $dropdown-item-padding-y $dropdown-item-padding-x;\n color: $dropdown-link-color;\n}\n","@mixin caret-down {\n border-top: $caret-width solid;\n border-right: $caret-width solid transparent;\n border-bottom: 0;\n border-left: $caret-width solid transparent;\n}\n\n@mixin caret-up {\n border-top: 0;\n border-right: $caret-width solid transparent;\n border-bottom: $caret-width solid;\n border-left: $caret-width solid transparent;\n}\n\n@mixin caret-right {\n border-top: $caret-width solid transparent;\n border-right: 0;\n border-bottom: $caret-width solid transparent;\n border-left: $caret-width solid;\n}\n\n@mixin caret-left {\n border-top: $caret-width solid transparent;\n border-right: $caret-width solid;\n border-bottom: $caret-width solid transparent;\n}\n\n@mixin caret($direction: down) {\n @if $enable-caret {\n &::after {\n display: inline-block;\n margin-left: $caret-spacing;\n vertical-align: $caret-vertical-align;\n content: \"\";\n @if $direction == down {\n @include caret-down;\n } @else if $direction == up {\n @include caret-up;\n } @else if $direction == right {\n @include caret-right;\n }\n }\n\n @if $direction == left {\n &::after {\n display: none;\n }\n\n &::before {\n display: inline-block;\n margin-right: $caret-spacing;\n vertical-align: $caret-vertical-align;\n content: \"\";\n @include caret-left;\n }\n }\n\n &:empty::after {\n margin-left: 0;\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n@mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y) {\n height: 0;\n margin: $margin-y 0;\n overflow: hidden;\n border-top: 1px solid $color;\n}\n","// stylelint-disable selector-no-qualifying-type\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle; // match .btn alignment given font-size hack above\n\n > .btn {\n position: relative;\n flex: 1 1 auto;\n\n // Bring the hover, focused, and \"active\" buttons to the front to overlay\n // the borders properly\n @include hover {\n z-index: 1;\n }\n &:focus,\n &:active,\n &.active {\n z-index: 1;\n }\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n\n .input-group {\n width: auto;\n }\n}\n\n.btn-group {\n // Prevent double borders when buttons are next to each other\n > .btn:not(:first-child),\n > .btn-group:not(:first-child) {\n margin-left: -$btn-border-width;\n }\n\n // Reset rounded corners\n > .btn:not(:last-child):not(.dropdown-toggle),\n > .btn-group:not(:last-child) > .btn {\n @include border-right-radius(0);\n }\n\n > .btn:not(:first-child),\n > .btn-group:not(:first-child) > .btn {\n @include border-left-radius(0);\n }\n}\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-sm > .btn { @extend .btn-sm; }\n.btn-group-lg > .btn { @extend .btn-lg; }\n\n\n//\n// Split button dropdowns\n//\n\n.dropdown-toggle-split {\n padding-right: $btn-padding-x * .75;\n padding-left: $btn-padding-x * .75;\n\n &::after,\n .dropup &::after,\n .dropright &::after {\n margin-left: 0;\n }\n\n .dropleft &::before {\n margin-right: 0;\n }\n}\n\n.btn-sm + .dropdown-toggle-split {\n padding-right: $btn-padding-x-sm * .75;\n padding-left: $btn-padding-x-sm * .75;\n}\n\n.btn-lg + .dropdown-toggle-split {\n padding-right: $btn-padding-x-lg * .75;\n padding-left: $btn-padding-x-lg * .75;\n}\n\n\n// The clickable button for toggling the menu\n// Set the same inset shadow as the :active state\n.btn-group.show .dropdown-toggle {\n @include box-shadow($btn-active-box-shadow);\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n @include box-shadow(none);\n }\n}\n\n\n//\n// Vertical button groups\n//\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n\n > .btn,\n > .btn-group {\n width: 100%;\n }\n\n > .btn:not(:first-child),\n > .btn-group:not(:first-child) {\n margin-top: -$btn-border-width;\n }\n\n // Reset rounded corners\n > .btn:not(:last-child):not(.dropdown-toggle),\n > .btn-group:not(:last-child) > .btn {\n @include border-bottom-radius(0);\n }\n\n > .btn:not(:first-child),\n > .btn-group:not(:first-child) > .btn {\n @include border-top-radius(0);\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n.btn-group-toggle {\n > .btn,\n > .btn-group > .btn {\n margin-bottom: 0; // Override default `<label>` value\n\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n }\n }\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Base styles\n//\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap; // For form validation feedback\n align-items: stretch;\n width: 100%;\n\n > .form-control,\n > .form-control-plaintext,\n > .custom-select,\n > .custom-file {\n position: relative; // For focus state's z-index\n flex: 1 1 auto;\n // Add width 1% and flex-basis auto to ensure that button will not wrap out\n // the column. Applies to IE Edge+ and Firefox. Chrome does not require this.\n width: 1%;\n margin-bottom: 0;\n\n + .form-control,\n + .custom-select,\n + .custom-file {\n margin-left: -$input-border-width;\n }\n }\n\n // Bring the \"active\" form control to the top of surrounding elements\n > .form-control:focus,\n > .custom-select:focus,\n > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3;\n }\n\n // Bring the custom file input above the label\n > .custom-file .custom-file-input:focus {\n z-index: 4;\n }\n\n > .form-control,\n > .custom-select {\n &:not(:last-child) { @include border-right-radius(0); }\n &:not(:first-child) { @include border-left-radius(0); }\n }\n\n // Custom file inputs have more complex markup, thus requiring different\n // border-radius overrides.\n > .custom-file {\n display: flex;\n align-items: center;\n\n &:not(:last-child) .custom-file-label,\n &:not(:last-child) .custom-file-label::after { @include border-right-radius(0); }\n &:not(:first-child) .custom-file-label { @include border-left-radius(0); }\n }\n}\n\n\n// Prepend and append\n//\n// While it requires one extra layer of HTML for each, dedicated prepend and\n// append elements allow us to 1) be less clever, 2) simplify our selectors, and\n// 3) support HTML5 form validation.\n\n.input-group-prepend,\n.input-group-append {\n display: flex;\n\n // Ensure buttons are always above inputs for more visually pleasing borders.\n // This isn't needed for `.input-group-text` since it shares the same border-color\n // as our inputs.\n .btn {\n position: relative;\n z-index: 2;\n\n &:focus {\n z-index: 3;\n }\n }\n\n .btn + .btn,\n .btn + .input-group-text,\n .input-group-text + .input-group-text,\n .input-group-text + .btn {\n margin-left: -$input-border-width;\n }\n}\n\n.input-group-prepend { margin-right: -$input-border-width; }\n.input-group-append { margin-left: -$input-border-width; }\n\n\n// Textual addons\n//\n// Serves as a catch-all element for any text or radio/checkbox input you wish\n// to prepend or append to an input.\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: $input-padding-y $input-padding-x;\n margin-bottom: 0; // Allow use of <label> elements by overriding our default margin-bottom\n @include font-size($input-font-size); // Match inputs\n font-weight: $font-weight-normal;\n line-height: $input-line-height;\n color: $input-group-addon-color;\n text-align: center;\n white-space: nowrap;\n background-color: $input-group-addon-bg;\n border: $input-border-width solid $input-group-addon-border-color;\n @include border-radius($input-border-radius);\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n\n// Sizing\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control:not(textarea),\n.input-group-lg > .custom-select {\n height: $input-height-lg;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .custom-select,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n padding: $input-padding-y-lg $input-padding-x-lg;\n @include font-size($input-font-size-lg);\n line-height: $input-line-height-lg;\n @include border-radius($input-border-radius-lg);\n}\n\n.input-group-sm > .form-control:not(textarea),\n.input-group-sm > .custom-select {\n height: $input-height-sm;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .custom-select,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n padding: $input-padding-y-sm $input-padding-x-sm;\n @include font-size($input-font-size-sm);\n line-height: $input-line-height-sm;\n @include border-radius($input-border-radius-sm);\n}\n\n.input-group-lg > .custom-select,\n.input-group-sm > .custom-select {\n padding-right: $custom-select-padding-x + $custom-select-indicator-padding;\n}\n\n\n// Prepend and append rounded corners\n//\n// These rulesets must come after the sizing ones to properly override sm and lg\n// border-radius values when extending. They're more specific than we'd like\n// with the `.input-group >` part, but without it, we cannot override the sizing.\n\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n @include border-right-radius(0);\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n @include border-left-radius(0);\n}\n","// Embedded icons from Open Iconic.\n// Released under MIT and copyright 2014 Waybury.\n// https://useiconic.com/open\n\n\n// Checkboxes and radios\n//\n// Base class takes care of all the key behavioral aspects.\n\n.custom-control {\n position: relative;\n display: block;\n min-height: $font-size-base * $line-height-base;\n padding-left: $custom-control-gutter + $custom-control-indicator-size;\n}\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: $custom-control-spacer-x;\n}\n\n.custom-control-input {\n position: absolute;\n z-index: -1; // Put the input behind the label so it doesn't overlay text\n opacity: 0;\n\n &:checked ~ .custom-control-label::before {\n color: $custom-control-indicator-checked-color;\n border-color: $custom-control-indicator-checked-border-color;\n @include gradient-bg($custom-control-indicator-checked-bg);\n @include box-shadow($custom-control-indicator-checked-box-shadow);\n }\n\n &:focus ~ .custom-control-label::before {\n // the mixin is not used here to make sure there is feedback\n @if $enable-shadows {\n box-shadow: $input-box-shadow, $input-focus-box-shadow;\n } @else {\n box-shadow: $custom-control-indicator-focus-box-shadow;\n }\n }\n\n &:focus:not(:checked) ~ .custom-control-label::before {\n border-color: $custom-control-indicator-focus-border-color;\n }\n\n &:not(:disabled):active ~ .custom-control-label::before {\n color: $custom-control-indicator-active-color;\n background-color: $custom-control-indicator-active-bg;\n border-color: $custom-control-indicator-active-border-color;\n @include box-shadow($custom-control-indicator-active-box-shadow);\n }\n\n &:disabled {\n ~ .custom-control-label {\n color: $custom-control-label-disabled-color;\n\n &::before {\n background-color: $custom-control-indicator-disabled-bg;\n }\n }\n }\n}\n\n// Custom control indicators\n//\n// Build the custom controls out of pseudo-elements.\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0;\n vertical-align: top;\n\n // Background-color and (when enabled) gradient\n &::before {\n position: absolute;\n top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2;\n left: -($custom-control-gutter + $custom-control-indicator-size);\n display: block;\n width: $custom-control-indicator-size;\n height: $custom-control-indicator-size;\n pointer-events: none;\n content: \"\";\n background-color: $custom-control-indicator-bg;\n border: $custom-control-indicator-border-color solid $custom-control-indicator-border-width;\n @include box-shadow($custom-control-indicator-box-shadow);\n }\n\n // Foreground (icon)\n &::after {\n position: absolute;\n top: ($font-size-base * $line-height-base - $custom-control-indicator-size) / 2;\n left: -($custom-control-gutter + $custom-control-indicator-size);\n display: block;\n width: $custom-control-indicator-size;\n height: $custom-control-indicator-size;\n content: \"\";\n background: no-repeat 50% / #{$custom-control-indicator-bg-size};\n }\n}\n\n\n// Checkboxes\n//\n// Tweak just a few things for checkboxes.\n\n.custom-checkbox {\n .custom-control-label::before {\n @include border-radius($custom-checkbox-indicator-border-radius);\n }\n\n .custom-control-input:checked ~ .custom-control-label {\n &::after {\n background-image: $custom-checkbox-indicator-icon-checked;\n }\n }\n\n .custom-control-input:indeterminate ~ .custom-control-label {\n &::before {\n border-color: $custom-checkbox-indicator-indeterminate-border-color;\n @include gradient-bg($custom-checkbox-indicator-indeterminate-bg);\n @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);\n }\n &::after {\n background-image: $custom-checkbox-indicator-icon-indeterminate;\n }\n }\n\n .custom-control-input:disabled {\n &:checked ~ .custom-control-label::before {\n background-color: $custom-control-indicator-checked-disabled-bg;\n }\n &:indeterminate ~ .custom-control-label::before {\n background-color: $custom-control-indicator-checked-disabled-bg;\n }\n }\n}\n\n// Radios\n//\n// Tweak just a few things for radios.\n\n.custom-radio {\n .custom-control-label::before {\n // stylelint-disable-next-line property-blacklist\n border-radius: $custom-radio-indicator-border-radius;\n }\n\n .custom-control-input:checked ~ .custom-control-label {\n &::after {\n background-image: $custom-radio-indicator-icon-checked;\n }\n }\n\n .custom-control-input:disabled {\n &:checked ~ .custom-control-label::before {\n background-color: $custom-control-indicator-checked-disabled-bg;\n }\n }\n}\n\n\n// switches\n//\n// Tweak a few things for switches\n\n.custom-switch {\n padding-left: $custom-switch-width + $custom-control-gutter;\n\n .custom-control-label {\n &::before {\n left: -($custom-switch-width + $custom-control-gutter);\n width: $custom-switch-width;\n pointer-events: all;\n // stylelint-disable-next-line property-blacklist\n border-radius: $custom-switch-indicator-border-radius;\n }\n\n &::after {\n top: calc(#{(($font-size-base * $line-height-base - $custom-control-indicator-size) / 2)} + #{$custom-control-indicator-border-width * 2});\n left: calc(#{-($custom-switch-width + $custom-control-gutter)} + #{$custom-control-indicator-border-width * 2});\n width: $custom-switch-indicator-size;\n height: $custom-switch-indicator-size;\n background-color: $custom-control-indicator-border-color;\n // stylelint-disable-next-line property-blacklist\n border-radius: $custom-switch-indicator-border-radius;\n @include transition(transform .15s ease-in-out, $custom-forms-transition);\n }\n }\n\n .custom-control-input:checked ~ .custom-control-label {\n &::after {\n background-color: $custom-control-indicator-bg;\n transform: translateX($custom-switch-width - $custom-control-indicator-size);\n }\n }\n\n .custom-control-input:disabled {\n &:checked ~ .custom-control-label::before {\n background-color: $custom-control-indicator-checked-disabled-bg;\n }\n }\n}\n\n\n// Select\n//\n// Replaces the browser default select with a custom one, mostly pulled from\n// https://primer.github.io/.\n//\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: $custom-select-height;\n padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;\n font-family: $custom-select-font-family;\n @include font-size($custom-select-font-size);\n font-weight: $custom-select-font-weight;\n line-height: $custom-select-line-height;\n color: $custom-select-color;\n vertical-align: middle;\n background: $custom-select-background;\n background-color: $custom-select-bg;\n border: $custom-select-border-width solid $custom-select-border-color;\n @include border-radius($custom-select-border-radius, 0);\n @include box-shadow($custom-select-box-shadow);\n appearance: none;\n\n &:focus {\n border-color: $custom-select-focus-border-color;\n outline: 0;\n @if $enable-shadows {\n box-shadow: $custom-select-box-shadow, $custom-select-focus-box-shadow;\n } @else {\n box-shadow: $custom-select-focus-box-shadow;\n }\n\n &::-ms-value {\n // For visual consistency with other platforms/browsers,\n // suppress the default white text on blue background highlight given to\n // the selected option text when the (still closed) <select> receives focus\n // in IE and (under certain conditions) Edge.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n }\n\n &[multiple],\n &[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: $custom-select-padding-x;\n background-image: none;\n }\n\n &:disabled {\n color: $custom-select-disabled-color;\n background-color: $custom-select-disabled-bg;\n }\n\n // Hides the default caret in IE11\n &::-ms-expand {\n display: none;\n }\n}\n\n.custom-select-sm {\n height: $custom-select-height-sm;\n padding-top: $custom-select-padding-y-sm;\n padding-bottom: $custom-select-padding-y-sm;\n padding-left: $custom-select-padding-x-sm;\n @include font-size($custom-select-font-size-sm);\n}\n\n.custom-select-lg {\n height: $custom-select-height-lg;\n padding-top: $custom-select-padding-y-lg;\n padding-bottom: $custom-select-padding-y-lg;\n padding-left: $custom-select-padding-x-lg;\n @include font-size($custom-select-font-size-lg);\n}\n\n\n// File\n//\n// Custom file input.\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: $custom-file-height;\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: $custom-file-height;\n margin: 0;\n opacity: 0;\n\n &:focus ~ .custom-file-label {\n border-color: $custom-file-focus-border-color;\n box-shadow: $custom-file-focus-box-shadow;\n }\n\n &:disabled ~ .custom-file-label {\n background-color: $custom-file-disabled-bg;\n }\n\n @each $lang, $value in $custom-file-text {\n &:lang(#{$lang}) ~ .custom-file-label::after {\n content: $value;\n }\n }\n\n ~ .custom-file-label[data-browse]::after {\n content: attr(data-browse);\n }\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: $custom-file-height;\n padding: $custom-file-padding-y $custom-file-padding-x;\n font-family: $custom-file-font-family;\n font-weight: $custom-file-font-weight;\n line-height: $custom-file-line-height;\n color: $custom-file-color;\n background-color: $custom-file-bg;\n border: $custom-file-border-width solid $custom-file-border-color;\n @include border-radius($custom-file-border-radius);\n @include box-shadow($custom-file-box-shadow);\n\n &::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: $custom-file-height-inner;\n padding: $custom-file-padding-y $custom-file-padding-x;\n line-height: $custom-file-line-height;\n color: $custom-file-button-color;\n content: \"Browse\";\n @include gradient-bg($custom-file-button-bg);\n border-left: inherit;\n @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);\n }\n}\n\n// Range\n//\n// Style range inputs the same across browsers. Vendor-specific rules for pseudo\n// elements cannot be mixed. As such, there are no shared styles for focus or\n// active states on prefixed selectors.\n\n.custom-range {\n width: 100%;\n height: calc(#{$custom-range-thumb-height} + #{$custom-range-thumb-focus-box-shadow-width * 2});\n padding: 0; // Need to reset padding\n background-color: transparent;\n appearance: none;\n\n &:focus {\n outline: none;\n\n // Pseudo-elements must be split across multiple rulesets to have an effect.\n // No box-shadow() mixin for focus accessibility.\n &::-webkit-slider-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n &::-moz-range-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n &::-ms-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }\n }\n\n &::-moz-focus-outer {\n border: 0;\n }\n\n &::-webkit-slider-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n margin-top: ($custom-range-track-height - $custom-range-thumb-height) / 2; // Webkit specific\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-webkit-slider-runnable-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent; // Why?\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent;\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-moz-range-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-moz-range-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent; // Firefox specific?\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n margin-top: 0; // Edge specific\n margin-right: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.\n margin-left: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n @include transition($custom-forms-transition);\n appearance: none;\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-ms-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: transparent;\n border-color: transparent;\n border-width: $custom-range-thumb-height / 2;\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-fill-lower {\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n\n &::-ms-fill-upper {\n margin-right: 15px; // arbitrary?\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n\n &:disabled {\n &::-webkit-slider-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n\n &::-webkit-slider-runnable-track {\n cursor: default;\n }\n\n &::-moz-range-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n\n &::-moz-range-track {\n cursor: default;\n }\n\n &::-ms-thumb {\n background-color: $custom-range-thumb-disabled-bg;\n }\n }\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n @include transition($custom-forms-transition);\n}\n","// Base class\n//\n// Kickstart any navigation component with a set of style resets. Works with\n// `<nav>`s or `<ul>`s.\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.nav-link {\n display: block;\n padding: $nav-link-padding-y $nav-link-padding-x;\n\n @include hover-focus {\n text-decoration: none;\n }\n\n // Disabled state lightens text\n &.disabled {\n color: $nav-link-disabled-color;\n pointer-events: none;\n cursor: default;\n }\n}\n\n//\n// Tabs\n//\n\n.nav-tabs {\n border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;\n\n .nav-item {\n margin-bottom: -$nav-tabs-border-width;\n }\n\n .nav-link {\n border: $nav-tabs-border-width solid transparent;\n @include border-top-radius($nav-tabs-border-radius);\n\n @include hover-focus {\n border-color: $nav-tabs-link-hover-border-color;\n }\n\n &.disabled {\n color: $nav-link-disabled-color;\n background-color: transparent;\n border-color: transparent;\n }\n }\n\n .nav-link.active,\n .nav-item.show .nav-link {\n color: $nav-tabs-link-active-color;\n background-color: $nav-tabs-link-active-bg;\n border-color: $nav-tabs-link-active-border-color;\n }\n\n .dropdown-menu {\n // Make dropdown border overlap tab border\n margin-top: -$nav-tabs-border-width;\n // Remove the top rounded corners here since there is a hard edge above the menu\n @include border-top-radius(0);\n }\n}\n\n\n//\n// Pills\n//\n\n.nav-pills {\n .nav-link {\n @include border-radius($nav-pills-border-radius);\n }\n\n .nav-link.active,\n .show > .nav-link {\n color: $nav-pills-link-active-color;\n background-color: $nav-pills-link-active-bg;\n }\n}\n\n\n//\n// Justified variants\n//\n\n.nav-fill {\n .nav-item {\n flex: 1 1 auto;\n text-align: center;\n }\n}\n\n.nav-justified {\n .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center;\n }\n}\n\n\n// Tabbable tabs\n//\n// Hide tabbable panes to start, show them when `.active`\n\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n","// Contents\n//\n// Navbar\n// Navbar brand\n// Navbar nav\n// Navbar text\n// Navbar divider\n// Responsive navbar\n// Navbar position\n// Navbar themes\n\n\n// Navbar\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap; // allow us to do the line break for collapsing content\n align-items: center;\n justify-content: space-between; // space out brand from logo\n padding: $navbar-padding-y $navbar-padding-x;\n\n // Because flex properties aren't inherited, we need to redeclare these first\n // few properties so that content nested within behave properly.\n > .container,\n > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n }\n}\n\n\n// Navbar brand\n//\n// Used for brand, project, or site names.\n\n.navbar-brand {\n display: inline-block;\n padding-top: $navbar-brand-padding-y;\n padding-bottom: $navbar-brand-padding-y;\n margin-right: $navbar-padding-x;\n @include font-size($navbar-brand-font-size);\n line-height: inherit;\n white-space: nowrap;\n\n @include hover-focus {\n text-decoration: none;\n }\n}\n\n\n// Navbar nav\n//\n// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).\n\n.navbar-nav {\n display: flex;\n flex-direction: column; // cannot use `inherit` to get the `.navbar`s value\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n\n .nav-link {\n padding-right: 0;\n padding-left: 0;\n }\n\n .dropdown-menu {\n position: static;\n float: none;\n }\n}\n\n\n// Navbar text\n//\n//\n\n.navbar-text {\n display: inline-block;\n padding-top: $nav-link-padding-y;\n padding-bottom: $nav-link-padding-y;\n}\n\n\n// Responsive navbar\n//\n// Custom styles for responsive collapsing and toggling of navbar contents.\n// Powered by the collapse Bootstrap JavaScript plugin.\n\n// When collapsed, prevent the toggleable navbar contents from appearing in\n// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`\n// on the `.navbar` parent.\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n // For always expanded or extra full navbars, ensure content aligns itself\n // properly vertically. Can be easily overridden with flex utilities.\n align-items: center;\n}\n\n// Button for toggling the navbar when in its collapsed state\n.navbar-toggler {\n padding: $navbar-toggler-padding-y $navbar-toggler-padding-x;\n @include font-size($navbar-toggler-font-size);\n line-height: 1;\n background-color: transparent; // remove default button style\n border: $border-width solid transparent; // remove default button style\n @include border-radius($navbar-toggler-border-radius);\n\n @include hover-focus {\n text-decoration: none;\n }\n}\n\n// Keep as a separate element so folks can easily override it with another icon\n// or image file as needed.\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: \"\";\n background: no-repeat center center;\n background-size: 100% 100%;\n}\n\n// Generate series of `.navbar-expand-*` responsive classes for configuring\n// where your navbar collapses.\n.navbar-expand {\n @each $breakpoint in map-keys($grid-breakpoints) {\n $next: breakpoint-next($breakpoint, $grid-breakpoints);\n $infix: breakpoint-infix($next, $grid-breakpoints);\n\n &#{$infix} {\n @include media-breakpoint-down($breakpoint) {\n > .container,\n > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n }\n\n @include media-breakpoint-up($next) {\n flex-flow: row nowrap;\n justify-content: flex-start;\n\n .navbar-nav {\n flex-direction: row;\n\n .dropdown-menu {\n position: absolute;\n }\n\n .nav-link {\n padding-right: $navbar-nav-link-padding-x;\n padding-left: $navbar-nav-link-padding-x;\n }\n }\n\n // For nesting containers, have to redeclare for alignment purposes\n > .container,\n > .container-fluid {\n flex-wrap: nowrap;\n }\n\n .navbar-collapse {\n display: flex !important; // stylelint-disable-line declaration-no-important\n\n // Changes flex-bases to auto because of an IE10 bug\n flex-basis: auto;\n }\n\n .navbar-toggler {\n display: none;\n }\n }\n }\n }\n}\n\n\n// Navbar themes\n//\n// Styles for switching between navbars with light or dark background.\n\n// Dark links against a light background\n.navbar-light {\n .navbar-brand {\n color: $navbar-light-brand-color;\n\n @include hover-focus {\n color: $navbar-light-brand-hover-color;\n }\n }\n\n .navbar-nav {\n .nav-link {\n color: $navbar-light-color;\n\n @include hover-focus {\n color: $navbar-light-hover-color;\n }\n\n &.disabled {\n color: $navbar-light-disabled-color;\n }\n }\n\n .show > .nav-link,\n .active > .nav-link,\n .nav-link.show,\n .nav-link.active {\n color: $navbar-light-active-color;\n }\n }\n\n .navbar-toggler {\n color: $navbar-light-color;\n border-color: $navbar-light-toggler-border-color;\n }\n\n .navbar-toggler-icon {\n background-image: $navbar-light-toggler-icon-bg;\n }\n\n .navbar-text {\n color: $navbar-light-color;\n a {\n color: $navbar-light-active-color;\n\n @include hover-focus {\n color: $navbar-light-active-color;\n }\n }\n }\n}\n\n// White links against a dark background\n.navbar-dark {\n .navbar-brand {\n color: $navbar-dark-brand-color;\n\n @include hover-focus {\n color: $navbar-dark-brand-hover-color;\n }\n }\n\n .navbar-nav {\n .nav-link {\n color: $navbar-dark-color;\n\n @include hover-focus {\n color: $navbar-dark-hover-color;\n }\n\n &.disabled {\n color: $navbar-dark-disabled-color;\n }\n }\n\n .show > .nav-link,\n .active > .nav-link,\n .nav-link.show,\n .nav-link.active {\n color: $navbar-dark-active-color;\n }\n }\n\n .navbar-toggler {\n color: $navbar-dark-color;\n border-color: $navbar-dark-toggler-border-color;\n }\n\n .navbar-toggler-icon {\n background-image: $navbar-dark-toggler-icon-bg;\n }\n\n .navbar-text {\n color: $navbar-dark-color;\n a {\n color: $navbar-dark-active-color;\n\n @include hover-focus {\n color: $navbar-dark-active-color;\n }\n }\n }\n}\n","//\n// Base styles\n//\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106\n word-wrap: break-word;\n background-color: $card-bg;\n background-clip: border-box;\n border: $card-border-width solid $card-border-color;\n @include border-radius($card-border-radius);\n\n > hr {\n margin-right: 0;\n margin-left: 0;\n }\n\n > .list-group:first-child {\n .list-group-item:first-child {\n @include border-top-radius($card-border-radius);\n }\n }\n\n > .list-group:last-child {\n .list-group-item:last-child {\n @include border-bottom-radius($card-border-radius);\n }\n }\n}\n\n.card-body {\n // Enable `flex-grow: 1` for decks and groups so that card blocks take up\n // as much space as possible, ensuring footers are aligned to the bottom.\n flex: 1 1 auto;\n padding: $card-spacer-x;\n color: $card-color;\n}\n\n.card-title {\n margin-bottom: $card-spacer-y;\n}\n\n.card-subtitle {\n margin-top: -$card-spacer-y / 2;\n margin-bottom: 0;\n}\n\n.card-text:last-child {\n margin-bottom: 0;\n}\n\n.card-link {\n @include hover {\n text-decoration: none;\n }\n\n + .card-link {\n margin-left: $card-spacer-x;\n }\n}\n\n//\n// Optional textual caps\n//\n\n.card-header {\n padding: $card-spacer-y $card-spacer-x;\n margin-bottom: 0; // Removes the default margin-bottom of <hN>\n color: $card-cap-color;\n background-color: $card-cap-bg;\n border-bottom: $card-border-width solid $card-border-color;\n\n &:first-child {\n @include border-radius($card-inner-border-radius $card-inner-border-radius 0 0);\n }\n\n + .list-group {\n .list-group-item:first-child {\n border-top: 0;\n }\n }\n}\n\n.card-footer {\n padding: $card-spacer-y $card-spacer-x;\n background-color: $card-cap-bg;\n border-top: $card-border-width solid $card-border-color;\n\n &:last-child {\n @include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius);\n }\n}\n\n\n//\n// Header navs\n//\n\n.card-header-tabs {\n margin-right: -$card-spacer-x / 2;\n margin-bottom: -$card-spacer-y;\n margin-left: -$card-spacer-x / 2;\n border-bottom: 0;\n}\n\n.card-header-pills {\n margin-right: -$card-spacer-x / 2;\n margin-left: -$card-spacer-x / 2;\n}\n\n// Card image\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: $card-img-overlay-padding;\n}\n\n.card-img {\n width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch\n @include border-radius($card-inner-border-radius);\n}\n\n// Card image caps\n.card-img-top {\n width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch\n @include border-top-radius($card-inner-border-radius);\n}\n\n.card-img-bottom {\n width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch\n @include border-bottom-radius($card-inner-border-radius);\n}\n\n\n// Card deck\n\n.card-deck {\n display: flex;\n flex-direction: column;\n\n .card {\n margin-bottom: $card-deck-margin;\n }\n\n @include media-breakpoint-up(sm) {\n flex-flow: row wrap;\n margin-right: -$card-deck-margin;\n margin-left: -$card-deck-margin;\n\n .card {\n display: flex;\n // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: $card-deck-margin;\n margin-bottom: 0; // Override the default\n margin-left: $card-deck-margin;\n }\n }\n}\n\n\n//\n// Card groups\n//\n\n.card-group {\n display: flex;\n flex-direction: column;\n\n // The child selector allows nested `.card` within `.card-group`\n // to display properly.\n > .card {\n margin-bottom: $card-group-margin;\n }\n\n @include media-breakpoint-up(sm) {\n flex-flow: row wrap;\n // The child selector allows nested `.card` within `.card-group`\n // to display properly.\n > .card {\n // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4\n flex: 1 0 0%;\n margin-bottom: 0;\n\n + .card {\n margin-left: 0;\n border-left: 0;\n }\n\n // Handle rounded corners\n @if $enable-rounded {\n &:not(:last-child) {\n @include border-right-radius(0);\n\n .card-img-top,\n .card-header {\n // stylelint-disable-next-line property-blacklist\n border-top-right-radius: 0;\n }\n .card-img-bottom,\n .card-footer {\n // stylelint-disable-next-line property-blacklist\n border-bottom-right-radius: 0;\n }\n }\n\n &:not(:first-child) {\n @include border-left-radius(0);\n\n .card-img-top,\n .card-header {\n // stylelint-disable-next-line property-blacklist\n border-top-left-radius: 0;\n }\n .card-img-bottom,\n .card-footer {\n // stylelint-disable-next-line property-blacklist\n border-bottom-left-radius: 0;\n }\n }\n }\n }\n }\n}\n\n\n//\n// Columns\n//\n\n.card-columns {\n .card {\n margin-bottom: $card-columns-margin;\n }\n\n @include media-breakpoint-up(sm) {\n column-count: $card-columns-count;\n column-gap: $card-columns-gap;\n orphans: 1;\n widows: 1;\n\n .card {\n display: inline-block; // Don't let them vertically span multiple columns\n width: 100%; // Don't let their width change\n }\n }\n}\n\n\n//\n// Accordion\n//\n\n.accordion {\n > .card {\n overflow: hidden;\n\n &:not(:first-of-type) {\n .card-header:first-child {\n @include border-radius(0);\n }\n\n &:not(:last-of-type) {\n border-bottom: 0;\n @include border-radius(0);\n }\n }\n\n &:first-of-type {\n border-bottom: 0;\n @include border-bottom-radius(0);\n }\n\n &:last-of-type {\n @include border-top-radius(0);\n }\n\n .card-header {\n margin-bottom: -$card-border-width;\n }\n }\n}\n",".breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: $breadcrumb-padding-y $breadcrumb-padding-x;\n margin-bottom: $breadcrumb-margin-bottom;\n list-style: none;\n background-color: $breadcrumb-bg;\n @include border-radius($breadcrumb-border-radius);\n}\n\n.breadcrumb-item {\n // The separator between breadcrumbs (by default, a forward-slash: \"/\")\n + .breadcrumb-item {\n padding-left: $breadcrumb-item-padding;\n\n &::before {\n display: inline-block; // Suppress underlining of the separator in modern browsers\n padding-right: $breadcrumb-item-padding;\n color: $breadcrumb-divider-color;\n content: $breadcrumb-divider;\n }\n }\n\n // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built\n // without `<ul>`s. The `::before` pseudo-element generates an element\n // *within* the .breadcrumb-item and thereby inherits the `text-decoration`.\n //\n // To trick IE into suppressing the underline, we give the pseudo-element an\n // underline and then immediately remove it.\n + .breadcrumb-item:hover::before {\n text-decoration: underline;\n }\n // stylelint-disable-next-line no-duplicate-selectors\n + .breadcrumb-item:hover::before {\n text-decoration: none;\n }\n\n &.active {\n color: $breadcrumb-active-color;\n }\n}\n",".pagination {\n display: flex;\n @include list-unstyled();\n @include border-radius();\n}\n\n.page-link {\n position: relative;\n display: block;\n padding: $pagination-padding-y $pagination-padding-x;\n margin-left: -$pagination-border-width;\n line-height: $pagination-line-height;\n color: $pagination-color;\n background-color: $pagination-bg;\n border: $pagination-border-width solid $pagination-border-color;\n\n &:hover {\n z-index: 2;\n color: $pagination-hover-color;\n text-decoration: none;\n background-color: $pagination-hover-bg;\n border-color: $pagination-hover-border-color;\n }\n\n &:focus {\n z-index: 2;\n outline: $pagination-focus-outline;\n box-shadow: $pagination-focus-box-shadow;\n }\n}\n\n.page-item {\n &:first-child {\n .page-link {\n margin-left: 0;\n @include border-left-radius($border-radius);\n }\n }\n &:last-child {\n .page-link {\n @include border-right-radius($border-radius);\n }\n }\n\n &.active .page-link {\n z-index: 1;\n color: $pagination-active-color;\n background-color: $pagination-active-bg;\n border-color: $pagination-active-border-color;\n }\n\n &.disabled .page-link {\n color: $pagination-disabled-color;\n pointer-events: none;\n // Opinionated: remove the \"hand\" cursor set previously for .page-link\n cursor: auto;\n background-color: $pagination-disabled-bg;\n border-color: $pagination-disabled-border-color;\n }\n}\n\n\n//\n// Sizing\n//\n\n.pagination-lg {\n @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg);\n}\n\n.pagination-sm {\n @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm);\n}\n","// Pagination\n\n@mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {\n .page-link {\n padding: $padding-y $padding-x;\n @include font-size($font-size);\n line-height: $line-height;\n }\n\n .page-item {\n &:first-child {\n .page-link {\n @include border-left-radius($border-radius);\n }\n }\n &:last-child {\n .page-link {\n @include border-right-radius($border-radius);\n }\n }\n }\n}\n","// Base class\n//\n// Requires one of the contextual, color modifier classes for `color` and\n// `background-color`.\n\n.badge {\n display: inline-block;\n padding: $badge-padding-y $badge-padding-x;\n @include font-size($badge-font-size);\n font-weight: $badge-font-weight;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n @include border-radius($badge-border-radius);\n @include transition($badge-transition);\n\n @at-root a#{&} {\n @include hover-focus {\n text-decoration: none;\n }\n }\n\n // Empty badges collapse automatically\n &:empty {\n display: none;\n }\n}\n\n// Quick fix for badges in buttons\n.btn .badge {\n position: relative;\n top: -1px;\n}\n\n// Pill badges\n//\n// Make them extra rounded with a modifier to replace v3's badges.\n\n.badge-pill {\n padding-right: $badge-pill-padding-x;\n padding-left: $badge-pill-padding-x;\n @include border-radius($badge-pill-border-radius);\n}\n\n// Colors\n//\n// Contextual variations (linked badges get darker on :hover).\n\n@each $color, $value in $theme-colors {\n .badge-#{$color} {\n @include badge-variant($value);\n }\n}\n","@mixin badge-variant($bg) {\n color: color-yiq($bg);\n background-color: $bg;\n\n @at-root a#{&} {\n @include hover-focus {\n color: color-yiq($bg);\n background-color: darken($bg, 10%);\n }\n\n &:focus,\n &.focus {\n outline: 0;\n box-shadow: 0 0 0 $badge-focus-width rgba($bg, .5);\n }\n }\n}\n",".jumbotron {\n padding: $jumbotron-padding ($jumbotron-padding / 2);\n margin-bottom: $jumbotron-padding;\n color: $jumbotron-color;\n background-color: $jumbotron-bg;\n @include border-radius($border-radius-lg);\n\n @include media-breakpoint-up(sm) {\n padding: ($jumbotron-padding * 2) $jumbotron-padding;\n }\n}\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n @include border-radius(0);\n}\n","//\n// Base styles\n//\n\n.alert {\n position: relative;\n padding: $alert-padding-y $alert-padding-x;\n margin-bottom: $alert-margin-bottom;\n border: $alert-border-width solid transparent;\n @include border-radius($alert-border-radius);\n}\n\n// Headings for larger alerts\n.alert-heading {\n // Specified to prevent conflicts of changing $headings-color\n color: inherit;\n}\n\n// Provide class for links that match alerts\n.alert-link {\n font-weight: $alert-link-font-weight;\n}\n\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissible {\n padding-right: $close-font-size + $alert-padding-x * 2;\n\n // Adjust close link position\n .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: $alert-padding-y $alert-padding-x;\n color: inherit;\n }\n}\n\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n@each $color, $value in $theme-colors {\n .alert-#{$color} {\n @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));\n }\n}\n","@mixin alert-variant($background, $border, $color) {\n color: $color;\n @include gradient-bg($background);\n border-color: $border;\n\n hr {\n border-top-color: darken($border, 5%);\n }\n\n .alert-link {\n color: darken($color, 10%);\n }\n}\n","// Disable animation if transitions are disabled\n@if $enable-transitions {\n @keyframes progress-bar-stripes {\n from { background-position: $progress-height 0; }\n to { background-position: 0 0; }\n }\n}\n\n.progress {\n display: flex;\n height: $progress-height;\n overflow: hidden; // force rounded corners by cropping it\n @include font-size($progress-font-size);\n background-color: $progress-bg;\n @include border-radius($progress-border-radius);\n @include box-shadow($progress-box-shadow);\n}\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: $progress-bar-color;\n text-align: center;\n white-space: nowrap;\n background-color: $progress-bar-bg;\n @include transition($progress-bar-transition);\n}\n\n.progress-bar-striped {\n @include gradient-striped();\n background-size: $progress-height $progress-height;\n}\n\n@if $enable-transitions {\n .progress-bar-animated {\n animation: progress-bar-stripes $progress-bar-animation-timing;\n\n @media (prefers-reduced-motion: reduce) {\n animation: none;\n }\n }\n}\n",".media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n","// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n display: flex;\n flex-direction: column;\n\n // No need to set list-style: none; since .list-group-item is block level\n padding-left: 0; // reset padding because ul and ol\n margin-bottom: 0;\n}\n\n\n// Interactive list items\n//\n// Use anchor or button elements instead of `li`s or `div`s to create interactive\n// list items. Includes an extra `.active` modifier class for selected items.\n\n.list-group-item-action {\n width: 100%; // For `<button>`s (anchors become 100% by default though)\n color: $list-group-action-color;\n text-align: inherit; // For `<button>`s (anchors inherit)\n\n // Hover state\n @include hover-focus {\n z-index: 1; // Place hover/focus items above their siblings for proper border styling\n color: $list-group-action-hover-color;\n text-decoration: none;\n background-color: $list-group-hover-bg;\n }\n\n &:active {\n color: $list-group-action-active-color;\n background-color: $list-group-action-active-bg;\n }\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: $list-group-item-padding-y $list-group-item-padding-x;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -$list-group-border-width;\n color: $list-group-color;\n background-color: $list-group-bg;\n border: $list-group-border-width solid $list-group-border-color;\n\n &:first-child {\n @include border-top-radius($list-group-border-radius);\n }\n\n &:last-child {\n margin-bottom: 0;\n @include border-bottom-radius($list-group-border-radius);\n }\n\n &.disabled,\n &:disabled {\n color: $list-group-disabled-color;\n pointer-events: none;\n background-color: $list-group-disabled-bg;\n }\n\n // Include both here for `<a>`s and `<button>`s\n &.active {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: $list-group-active-color;\n background-color: $list-group-active-bg;\n border-color: $list-group-active-border-color;\n }\n}\n\n\n// Horizontal\n//\n// Change the layout of list group items from vertical (default) to horizontal.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .list-group-horizontal#{$infix} {\n flex-direction: row;\n\n .list-group-item {\n margin-right: -$list-group-border-width;\n margin-bottom: 0;\n\n &:first-child {\n @include border-left-radius($list-group-border-radius);\n @include border-top-right-radius(0);\n }\n\n &:last-child {\n margin-right: 0;\n @include border-right-radius($list-group-border-radius);\n @include border-bottom-left-radius(0);\n }\n }\n }\n }\n}\n\n\n// Flush list items\n//\n// Remove borders and border-radius to keep list group items edge-to-edge. Most\n// useful within other components (e.g., cards).\n\n.list-group-flush {\n .list-group-item {\n border-right: 0;\n border-left: 0;\n @include border-radius(0);\n\n &:last-child {\n margin-bottom: -$list-group-border-width;\n }\n }\n\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n }\n }\n\n &:last-child {\n .list-group-item:last-child {\n margin-bottom: 0;\n border-bottom: 0;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n@each $color, $value in $theme-colors {\n @include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6));\n}\n","// List Groups\n\n@mixin list-group-item-variant($state, $background, $color) {\n .list-group-item-#{$state} {\n color: $color;\n background-color: $background;\n\n &.list-group-item-action {\n @include hover-focus {\n color: $color;\n background-color: darken($background, 5%);\n }\n\n &.active {\n color: $white;\n background-color: $color;\n border-color: $color;\n }\n }\n }\n}\n",".close {\n float: right;\n @include font-size($close-font-size);\n font-weight: $close-font-weight;\n line-height: 1;\n color: $close-color;\n text-shadow: $close-text-shadow;\n opacity: .5;\n\n // Override <a>'s hover style\n @include hover {\n color: $close-color;\n text-decoration: none;\n }\n\n &:not(:disabled):not(.disabled) {\n @include hover-focus {\n opacity: .75;\n }\n }\n}\n\n// Additional properties for button version\n// iOS requires the button element instead of an anchor tag.\n// If you want the anchor version, it requires `href=\"#\"`.\n// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n// stylelint-disable-next-line selector-no-qualifying-type\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n appearance: none;\n}\n\n// Future-proof disabling of clicks on `<a>` elements\n\n// stylelint-disable-next-line selector-no-qualifying-type\na.close.disabled {\n pointer-events: none;\n}\n",".toast {\n max-width: $toast-max-width;\n overflow: hidden; // cheap rounded corners on nested items\n @include font-size($toast-font-size);\n color: $toast-color;\n background-color: $toast-background-color;\n background-clip: padding-box;\n border: $toast-border-width solid $toast-border-color;\n box-shadow: $toast-box-shadow;\n backdrop-filter: blur(10px);\n opacity: 0;\n @include border-radius($toast-border-radius);\n\n &:not(:last-child) {\n margin-bottom: $toast-padding-x;\n }\n\n &.showing {\n opacity: 1;\n }\n\n &.show {\n display: block;\n opacity: 1;\n }\n\n &.hide {\n display: none;\n }\n}\n\n.toast-header {\n display: flex;\n align-items: center;\n padding: $toast-padding-y $toast-padding-x;\n color: $toast-header-color;\n background-color: $toast-header-background-color;\n background-clip: padding-box;\n border-bottom: $toast-border-width solid $toast-header-border-color;\n}\n\n.toast-body {\n padding: $toast-padding-x; // apply to both vertical and horizontal\n}\n","// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and stuff\n\n\n.modal-open {\n // Kill the scroll on the body\n overflow: hidden;\n\n .modal {\n overflow-x: hidden;\n overflow-y: auto;\n }\n}\n\n// Container that the modal scrolls within\n.modal {\n position: fixed;\n top: 0;\n left: 0;\n z-index: $zindex-modal;\n display: none;\n width: 100%;\n height: 100%;\n overflow: hidden;\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a\n // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342\n // See also https://github.com/twbs/bootstrap/issues/17695\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: $modal-dialog-margin;\n // allow clicks to pass through for custom click handling to close modal\n pointer-events: none;\n\n // When fading in the modal, animate it to slide down\n .modal.fade & {\n @include transition($modal-transition);\n transform: $modal-fade-transform;\n }\n .modal.show & {\n transform: $modal-show-transform;\n }\n}\n\n.modal-dialog-scrollable {\n display: flex; // IE10/11\n max-height: calc(100% - #{$modal-dialog-margin * 2});\n\n .modal-content {\n max-height: calc(100vh - #{$modal-dialog-margin * 2}); // IE10/11\n overflow: hidden;\n }\n\n .modal-header,\n .modal-footer {\n flex-shrink: 0;\n }\n\n .modal-body {\n overflow-y: auto;\n }\n}\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - #{$modal-dialog-margin * 2});\n\n // Ensure `modal-dialog-centered` extends the full height of the view (IE10/11)\n &::before {\n display: block; // IE10\n height: calc(100vh - #{$modal-dialog-margin * 2});\n content: \"\";\n }\n\n // Ensure `.modal-body` shows scrollbar (IE10/11)\n &.modal-dialog-scrollable {\n flex-direction: column;\n justify-content: center;\n height: 100%;\n\n .modal-content {\n max-height: none;\n }\n\n &::before {\n content: none;\n }\n }\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`\n // counteract the pointer-events: none; in the .modal-dialog\n color: $modal-content-color;\n pointer-events: auto;\n background-color: $modal-content-bg;\n background-clip: padding-box;\n border: $modal-content-border-width solid $modal-content-border-color;\n @include border-radius($modal-content-border-radius);\n @include box-shadow($modal-content-box-shadow-xs);\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n z-index: $zindex-modal-backdrop;\n width: 100vw;\n height: 100vh;\n background-color: $modal-backdrop-bg;\n\n // Fade for backdrop\n &.fade { opacity: 0; }\n &.show { opacity: $modal-backdrop-opacity; }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n display: flex;\n align-items: flex-start; // so the close btn always stays on the upper right corner\n justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends\n padding: $modal-header-padding;\n border-bottom: $modal-header-border-width solid $modal-header-border-color;\n @include border-top-radius($modal-content-border-radius);\n\n .close {\n padding: $modal-header-padding;\n // auto on the left force icon to the right even when there is no .modal-title\n margin: (-$modal-header-padding-y) (-$modal-header-padding-x) (-$modal-header-padding-y) auto;\n }\n}\n\n// Title text within header\n.modal-title {\n margin-bottom: 0;\n line-height: $modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n // Enable `flex-grow: 1` so that the body take up as much space as possible\n // when should there be a fixed height on `.modal-dialog`.\n flex: 1 1 auto;\n padding: $modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n display: flex;\n align-items: center; // vertically center\n justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items\n padding: $modal-inner-padding;\n border-top: $modal-footer-border-width solid $modal-footer-border-color;\n @include border-bottom-radius($modal-content-border-radius);\n\n // Easily place margin between footer elements\n > :not(:first-child) { margin-left: .25rem; }\n > :not(:last-child) { margin-right: .25rem; }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@include media-breakpoint-up(sm) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n max-width: $modal-md;\n margin: $modal-dialog-margin-y-sm-up auto;\n }\n\n .modal-dialog-scrollable {\n max-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});\n\n .modal-content {\n max-height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});\n }\n }\n\n .modal-dialog-centered {\n min-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});\n\n &::before {\n height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});\n }\n }\n\n .modal-content {\n @include box-shadow($modal-content-box-shadow-sm-up);\n }\n\n .modal-sm { max-width: $modal-sm; }\n}\n\n@include media-breakpoint-up(lg) {\n .modal-lg,\n .modal-xl {\n max-width: $modal-lg;\n }\n}\n\n@include media-breakpoint-up(xl) {\n .modal-xl { max-width: $modal-xl; }\n}\n","// Base class\n.tooltip {\n position: absolute;\n z-index: $zindex-tooltip;\n display: block;\n margin: $tooltip-margin;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n @include reset-text();\n @include font-size($tooltip-font-size);\n // Allow breaking very long words so they don't overflow the tooltip's bounds\n word-wrap: break-word;\n opacity: 0;\n\n &.show { opacity: $tooltip-opacity; }\n\n .arrow {\n position: absolute;\n display: block;\n width: $tooltip-arrow-width;\n height: $tooltip-arrow-height;\n\n &::before {\n position: absolute;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n }\n }\n}\n\n.bs-tooltip-top {\n padding: $tooltip-arrow-height 0;\n\n .arrow {\n bottom: 0;\n\n &::before {\n top: 0;\n border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;\n border-top-color: $tooltip-arrow-color;\n }\n }\n}\n\n.bs-tooltip-right {\n padding: 0 $tooltip-arrow-height;\n\n .arrow {\n left: 0;\n width: $tooltip-arrow-height;\n height: $tooltip-arrow-width;\n\n &::before {\n right: 0;\n border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;\n border-right-color: $tooltip-arrow-color;\n }\n }\n}\n\n.bs-tooltip-bottom {\n padding: $tooltip-arrow-height 0;\n\n .arrow {\n top: 0;\n\n &::before {\n bottom: 0;\n border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;\n border-bottom-color: $tooltip-arrow-color;\n }\n }\n}\n\n.bs-tooltip-left {\n padding: 0 $tooltip-arrow-height;\n\n .arrow {\n right: 0;\n width: $tooltip-arrow-height;\n height: $tooltip-arrow-width;\n\n &::before {\n left: 0;\n border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;\n border-left-color: $tooltip-arrow-color;\n }\n }\n}\n\n.bs-tooltip-auto {\n &[x-placement^=\"top\"] {\n @extend .bs-tooltip-top;\n }\n &[x-placement^=\"right\"] {\n @extend .bs-tooltip-right;\n }\n &[x-placement^=\"bottom\"] {\n @extend .bs-tooltip-bottom;\n }\n &[x-placement^=\"left\"] {\n @extend .bs-tooltip-left;\n }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: $tooltip-max-width;\n padding: $tooltip-padding-y $tooltip-padding-x;\n color: $tooltip-color;\n text-align: center;\n background-color: $tooltip-bg;\n @include border-radius($tooltip-border-radius);\n}\n","@mixin reset-text {\n font-family: $font-family-base;\n // We deliberately do NOT reset font-size or word-wrap.\n font-style: normal;\n font-weight: $font-weight-normal;\n line-height: $line-height-base;\n text-align: left; // Fallback for where `start` is not supported\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n}\n",".popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: $zindex-popover;\n display: block;\n max-width: $popover-max-width;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n @include reset-text();\n @include font-size($popover-font-size);\n // Allow breaking very long words so they don't overflow the popover's bounds\n word-wrap: break-word;\n background-color: $popover-bg;\n background-clip: padding-box;\n border: $popover-border-width solid $popover-border-color;\n @include border-radius($popover-border-radius);\n @include box-shadow($popover-box-shadow);\n\n .arrow {\n position: absolute;\n display: block;\n width: $popover-arrow-width;\n height: $popover-arrow-height;\n margin: 0 $border-radius-lg;\n\n &::before,\n &::after {\n position: absolute;\n display: block;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n }\n }\n}\n\n.bs-popover-top {\n margin-bottom: $popover-arrow-height;\n\n > .arrow {\n bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);\n\n &::before {\n bottom: 0;\n border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;\n border-top-color: $popover-arrow-outer-color;\n }\n\n &::after {\n bottom: $popover-border-width;\n border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;\n border-top-color: $popover-arrow-color;\n }\n }\n}\n\n.bs-popover-right {\n margin-left: $popover-arrow-height;\n\n > .arrow {\n left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);\n width: $popover-arrow-height;\n height: $popover-arrow-width;\n margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners\n\n &::before {\n left: 0;\n border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;\n border-right-color: $popover-arrow-outer-color;\n }\n\n &::after {\n left: $popover-border-width;\n border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;\n border-right-color: $popover-arrow-color;\n }\n }\n}\n\n.bs-popover-bottom {\n margin-top: $popover-arrow-height;\n\n > .arrow {\n top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);\n\n &::before {\n top: 0;\n border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);\n border-bottom-color: $popover-arrow-outer-color;\n }\n\n &::after {\n top: $popover-border-width;\n border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);\n border-bottom-color: $popover-arrow-color;\n }\n }\n\n // This will remove the popover-header's border just below the arrow\n .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: $popover-arrow-width;\n margin-left: -$popover-arrow-width / 2;\n content: \"\";\n border-bottom: $popover-border-width solid $popover-header-bg;\n }\n}\n\n.bs-popover-left {\n margin-right: $popover-arrow-height;\n\n > .arrow {\n right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);\n width: $popover-arrow-height;\n height: $popover-arrow-width;\n margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners\n\n &::before {\n right: 0;\n border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;\n border-left-color: $popover-arrow-outer-color;\n }\n\n &::after {\n right: $popover-border-width;\n border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;\n border-left-color: $popover-arrow-color;\n }\n }\n}\n\n.bs-popover-auto {\n &[x-placement^=\"top\"] {\n @extend .bs-popover-top;\n }\n &[x-placement^=\"right\"] {\n @extend .bs-popover-right;\n }\n &[x-placement^=\"bottom\"] {\n @extend .bs-popover-bottom;\n }\n &[x-placement^=\"left\"] {\n @extend .bs-popover-left;\n }\n}\n\n\n// Offset the popover to account for the popover arrow\n.popover-header {\n padding: $popover-header-padding-y $popover-header-padding-x;\n margin-bottom: 0; // Reset the default from Reboot\n @include font-size($font-size-base);\n color: $popover-header-color;\n background-color: $popover-header-bg;\n border-bottom: $popover-border-width solid darken($popover-header-bg, 5%);\n $offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width});\n @include border-top-radius($offset-border-width);\n\n &:empty {\n display: none;\n }\n}\n\n.popover-body {\n padding: $popover-body-padding-y $popover-body-padding-x;\n color: $popover-body-color;\n}\n","// Notes on the classes:\n//\n// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically)\n// even when their scroll action started on a carousel, but for compatibility (with Firefox)\n// we're preventing all actions instead\n// 2. The .carousel-item-left and .carousel-item-right is used to indicate where\n// the active slide is heading.\n// 3. .active.carousel-item is the current slide.\n// 4. .active.carousel-item-left and .active.carousel-item-right is the current\n// slide in its in-transition state. Only one of these occurs at a time.\n// 5. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right\n// is the upcoming slide in transition.\n\n.carousel {\n position: relative;\n}\n\n.carousel.pointer-event {\n touch-action: pan-y;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n @include clearfix();\n}\n\n.carousel-item {\n position: relative;\n display: none;\n float: left;\n width: 100%;\n margin-right: -100%;\n backface-visibility: hidden;\n @include transition($carousel-transition);\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n}\n\n.carousel-item-next:not(.carousel-item-left),\n.active.carousel-item-right {\n transform: translateX(100%);\n}\n\n.carousel-item-prev:not(.carousel-item-right),\n.active.carousel-item-left {\n transform: translateX(-100%);\n}\n\n\n//\n// Alternate transitions\n//\n\n.carousel-fade {\n .carousel-item {\n opacity: 0;\n transition-property: opacity;\n transform: none;\n }\n\n .carousel-item.active,\n .carousel-item-next.carousel-item-left,\n .carousel-item-prev.carousel-item-right {\n z-index: 1;\n opacity: 1;\n }\n\n .active.carousel-item-left,\n .active.carousel-item-right {\n z-index: 0;\n opacity: 0;\n @include transition(0s $carousel-transition-duration opacity);\n }\n}\n\n\n//\n// Left/right controls for nav\n//\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n z-index: 1;\n // Use flex for alignment (1-3)\n display: flex; // 1. allow flex styles\n align-items: center; // 2. vertically center contents\n justify-content: center; // 3. horizontally center contents\n width: $carousel-control-width;\n color: $carousel-control-color;\n text-align: center;\n opacity: $carousel-control-opacity;\n @include transition($carousel-control-transition);\n\n // Hover/focus state\n @include hover-focus {\n color: $carousel-control-color;\n text-decoration: none;\n outline: 0;\n opacity: $carousel-control-hover-opacity;\n }\n}\n.carousel-control-prev {\n left: 0;\n @if $enable-gradients {\n background: linear-gradient(90deg, rgba($black, .25), rgba($black, .001));\n }\n}\n.carousel-control-next {\n right: 0;\n @if $enable-gradients {\n background: linear-gradient(270deg, rgba($black, .25), rgba($black, .001));\n }\n}\n\n// Icons for within\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: $carousel-control-icon-width;\n height: $carousel-control-icon-width;\n background: no-repeat 50% / 100% 100%;\n}\n.carousel-control-prev-icon {\n background-image: $carousel-control-prev-icon-bg;\n}\n.carousel-control-next-icon {\n background-image: $carousel-control-next-icon-bg;\n}\n\n\n// Optional indicator pips\n//\n// Add an ordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0; // override <ol> default\n // Use the .carousel-control's width as margin so we don't overlay those\n margin-right: $carousel-control-width;\n margin-left: $carousel-control-width;\n list-style: none;\n\n li {\n box-sizing: content-box;\n flex: 0 1 auto;\n width: $carousel-indicator-width;\n height: $carousel-indicator-height;\n margin-right: $carousel-indicator-spacer;\n margin-left: $carousel-indicator-spacer;\n text-indent: -999px;\n cursor: pointer;\n background-color: $carousel-indicator-active-bg;\n background-clip: padding-box;\n // Use transparent borders to increase the hit area by 10px on top and bottom.\n border-top: $carousel-indicator-hit-area-height solid transparent;\n border-bottom: $carousel-indicator-hit-area-height solid transparent;\n opacity: .5;\n @include transition($carousel-indicator-transition);\n }\n\n .active {\n opacity: 1;\n }\n}\n\n\n// Optional captions\n//\n//\n\n.carousel-caption {\n position: absolute;\n right: (100% - $carousel-caption-width) / 2;\n bottom: 20px;\n left: (100% - $carousel-caption-width) / 2;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: $carousel-caption-color;\n text-align: center;\n}\n","@mixin clearfix() {\n &::after {\n display: block;\n clear: both;\n content: \"\";\n }\n}\n","//\n// Rotating border\n//\n\n@keyframes spinner-border {\n to { transform: rotate(360deg); }\n}\n\n.spinner-border {\n display: inline-block;\n width: $spinner-width;\n height: $spinner-height;\n vertical-align: text-bottom;\n border: $spinner-border-width solid currentColor;\n border-right-color: transparent;\n // stylelint-disable-next-line property-blacklist\n border-radius: 50%;\n animation: spinner-border .75s linear infinite;\n}\n\n.spinner-border-sm {\n width: $spinner-width-sm;\n height: $spinner-height-sm;\n border-width: $spinner-border-width-sm;\n}\n\n//\n// Growing circle\n//\n\n@keyframes spinner-grow {\n 0% {\n transform: scale(0);\n }\n 50% {\n opacity: 1;\n }\n}\n\n.spinner-grow {\n display: inline-block;\n width: $spinner-width;\n height: $spinner-height;\n vertical-align: text-bottom;\n background-color: currentColor;\n // stylelint-disable-next-line property-blacklist\n border-radius: 50%;\n opacity: 0;\n animation: spinner-grow .75s linear infinite;\n}\n\n.spinner-grow-sm {\n width: $spinner-width-sm;\n height: $spinner-height-sm;\n}\n","// stylelint-disable declaration-no-important\n\n.align-baseline { vertical-align: baseline !important; } // Browser default\n.align-top { vertical-align: top !important; }\n.align-middle { vertical-align: middle !important; }\n.align-bottom { vertical-align: bottom !important; }\n.align-text-bottom { vertical-align: text-bottom !important; }\n.align-text-top { vertical-align: text-top !important; }\n","// stylelint-disable declaration-no-important\n\n// Contextual backgrounds\n\n@mixin bg-variant($parent, $color) {\n #{$parent} {\n background-color: $color !important;\n }\n a#{$parent},\n button#{$parent} {\n @include hover-focus {\n background-color: darken($color, 10%) !important;\n }\n }\n}\n\n@mixin bg-gradient-variant($parent, $color) {\n #{$parent} {\n background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;\n }\n}\n","// stylelint-disable declaration-no-important\n\n@each $color, $value in $theme-colors {\n @include bg-variant(\".bg-#{$color}\", $value);\n}\n\n@if $enable-gradients {\n @each $color, $value in $theme-colors {\n @include bg-gradient-variant(\".bg-gradient-#{$color}\", $value);\n }\n}\n\n.bg-white {\n background-color: $white !important;\n}\n\n.bg-transparent {\n background-color: transparent !important;\n}\n","// stylelint-disable property-blacklist, declaration-no-important\n\n//\n// Border\n//\n\n.border { border: $border-width solid $border-color !important; }\n.border-top { border-top: $border-width solid $border-color !important; }\n.border-right { border-right: $border-width solid $border-color !important; }\n.border-bottom { border-bottom: $border-width solid $border-color !important; }\n.border-left { border-left: $border-width solid $border-color !important; }\n\n.border-0 { border: 0 !important; }\n.border-top-0 { border-top: 0 !important; }\n.border-right-0 { border-right: 0 !important; }\n.border-bottom-0 { border-bottom: 0 !important; }\n.border-left-0 { border-left: 0 !important; }\n\n@each $color, $value in $theme-colors {\n .border-#{$color} {\n border-color: $value !important;\n }\n}\n\n.border-white {\n border-color: $white !important;\n}\n\n//\n// Border-radius\n//\n\n.rounded-sm {\n border-radius: $border-radius-sm !important;\n}\n\n.rounded {\n border-radius: $border-radius !important;\n}\n\n.rounded-top {\n border-top-left-radius: $border-radius !important;\n border-top-right-radius: $border-radius !important;\n}\n\n.rounded-right {\n border-top-right-radius: $border-radius !important;\n border-bottom-right-radius: $border-radius !important;\n}\n\n.rounded-bottom {\n border-bottom-right-radius: $border-radius !important;\n border-bottom-left-radius: $border-radius !important;\n}\n\n.rounded-left {\n border-top-left-radius: $border-radius !important;\n border-bottom-left-radius: $border-radius !important;\n}\n\n.rounded-lg {\n border-radius: $border-radius-lg !important;\n}\n\n.rounded-circle {\n border-radius: 50% !important;\n}\n\n.rounded-pill {\n border-radius: $rounded-pill !important;\n}\n\n.rounded-0 {\n border-radius: 0 !important;\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n\n &::before {\n display: block;\n content: \"\";\n }\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n }\n}\n\n@each $embed-responsive-aspect-ratio in $embed-responsive-aspect-ratios {\n $embed-responsive-aspect-ratio-x: nth($embed-responsive-aspect-ratio, 1);\n $embed-responsive-aspect-ratio-y: nth($embed-responsive-aspect-ratio, 2);\n\n .embed-responsive-#{$embed-responsive-aspect-ratio-x}by#{$embed-responsive-aspect-ratio-y} {\n &::before {\n padding-top: percentage($embed-responsive-aspect-ratio-y / $embed-responsive-aspect-ratio-x);\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .float#{$infix}-left { float: left !important; }\n .float#{$infix}-right { float: right !important; }\n .float#{$infix}-none { float: none !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n@each $value in $overflows {\n .overflow-#{$value} { overflow: $value !important; }\n}\n","// stylelint-disable declaration-no-important\n\n// Common values\n@each $position in $positions {\n .position-#{$position} { position: $position !important; }\n}\n\n// Shorthand\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: $zindex-fixed;\n}\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: $zindex-fixed;\n}\n\n.sticky-top {\n @supports (position: sticky) {\n position: sticky;\n top: 0;\n z-index: $zindex-sticky;\n }\n}\n","//\n// Screenreaders\n//\n\n.sr-only {\n @include sr-only();\n}\n\n.sr-only-focusable {\n @include sr-only-focusable();\n}\n","// Only display content to screen readers\n//\n// See: https://a11yproject.com/posts/how-to-hide-content/\n// See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/\n\n@mixin sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n//\n// Useful for \"Skip to main content\" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n//\n// Credit: HTML5 Boilerplate\n\n@mixin sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal;\n }\n}\n","// stylelint-disable declaration-no-important\n\n.shadow-sm { box-shadow: $box-shadow-sm !important; }\n.shadow { box-shadow: $box-shadow !important; }\n.shadow-lg { box-shadow: $box-shadow-lg !important; }\n.shadow-none { box-shadow: none !important; }\n","// stylelint-disable declaration-no-important\n\n// Width and height\n\n@each $prop, $abbrev in (width: w, height: h) {\n @each $size, $length in $sizes {\n .#{$abbrev}-#{$size} { #{$prop}: $length !important; }\n }\n}\n\n.mw-100 { max-width: 100% !important; }\n.mh-100 { max-height: 100% !important; }\n\n// Viewport additional helpers\n\n.min-vw-100 { min-width: 100vw !important; }\n.min-vh-100 { min-height: 100vh !important; }\n\n.vw-100 { width: 100vw !important; }\n.vh-100 { height: 100vh !important; }\n","//\n// Stretched link\n//\n\n.stretched-link {\n &::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1;\n // Just in case `pointer-events: none` is set on a parent\n pointer-events: auto;\n content: \"\";\n // IE10 bugfix, see https://stackoverflow.com/questions/16947967/ie10-hover-pseudo-class-doesnt-work-without-background-color\n background-color: rgba(0, 0, 0, 0);\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Text\n//\n\n.text-monospace { font-family: $font-family-monospace !important; }\n\n// Alignment\n\n.text-justify { text-align: justify !important; }\n.text-wrap { white-space: normal !important; }\n.text-nowrap { white-space: nowrap !important; }\n.text-truncate { @include text-truncate; }\n\n// Responsive alignment\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .text#{$infix}-left { text-align: left !important; }\n .text#{$infix}-right { text-align: right !important; }\n .text#{$infix}-center { text-align: center !important; }\n }\n}\n\n// Transformation\n\n.text-lowercase { text-transform: lowercase !important; }\n.text-uppercase { text-transform: uppercase !important; }\n.text-capitalize { text-transform: capitalize !important; }\n\n// Weight and italics\n\n.font-weight-light { font-weight: $font-weight-light !important; }\n.font-weight-lighter { font-weight: $font-weight-lighter !important; }\n.font-weight-normal { font-weight: $font-weight-normal !important; }\n.font-weight-bold { font-weight: $font-weight-bold !important; }\n.font-weight-bolder { font-weight: $font-weight-bolder !important; }\n.font-italic { font-style: italic !important; }\n\n// Contextual colors\n\n.text-white { color: $white !important; }\n\n@each $color, $value in $theme-colors {\n @include text-emphasis-variant(\".text-#{$color}\", $value);\n}\n\n.text-body { color: $body-color !important; }\n.text-muted { color: $text-muted !important; }\n\n.text-black-50 { color: rgba($black, .5) !important; }\n.text-white-50 { color: rgba($white, .5) !important; }\n\n// Misc\n\n.text-hide {\n @include text-hide($ignore-warning: true);\n}\n\n.text-decoration-none { text-decoration: none !important; }\n\n.text-break {\n word-break: break-word !important; // IE & < Edge 18\n overflow-wrap: break-word !important;\n}\n\n// Reset\n\n.text-reset { color: inherit !important; }\n","// Text truncate\n// Requires inline-block or block for proper styling\n\n@mixin text-truncate() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","// stylelint-disable declaration-no-important\n\n// Typography\n\n@mixin text-emphasis-variant($parent, $color) {\n #{$parent} {\n color: $color !important;\n }\n @if $emphasized-link-hover-darken-percentage != 0 {\n a#{$parent} {\n @include hover-focus {\n color: darken($color, $emphasized-link-hover-darken-percentage) !important;\n }\n }\n }\n}\n","// CSS image replacement\n@mixin text-hide($ignore-warning: false) {\n // stylelint-disable-next-line font-family-no-missing-generic-family-keyword\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n\n @include deprecate(\"`text-hide()`\", \"v4.1.0\", \"v5\", $ignore-warning);\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Visibility utilities\n//\n\n.visible {\n visibility: visible !important;\n}\n\n.invisible {\n visibility: hidden !important;\n}\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type\n\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request:\n// https://www.phpied.com/delay-loading-your-print-css/\n// ==========================================================================\n\n@if $enable-print-styles {\n @media print {\n *,\n *::before,\n *::after {\n // Bootstrap specific; comment out `color` and `background`\n //color: $black !important; // Black prints faster\n text-shadow: none !important;\n //background: transparent !important;\n box-shadow: none !important;\n }\n\n a {\n &:not(.btn) {\n text-decoration: underline;\n }\n }\n\n // Bootstrap specific; comment the following selector out\n //a[href]::after {\n // content: \" (\" attr(href) \")\";\n //}\n\n abbr[title]::after {\n content: \" (\" attr(title) \")\";\n }\n\n // Bootstrap specific; comment the following selector out\n //\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n //\n\n //a[href^=\"#\"]::after,\n //a[href^=\"javascript:\"]::after {\n // content: \"\";\n //}\n\n pre {\n white-space: pre-wrap !important;\n }\n pre,\n blockquote {\n border: $border-width solid $gray-500; // Bootstrap custom code; using `$border-width` instead of 1px\n page-break-inside: avoid;\n }\n\n //\n // Printing Tables:\n // http://css-discuss.incutio.com/wiki/Printing_Tables\n //\n\n thead {\n display: table-header-group;\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Specify a size and min-width to make printing closer across browsers.\n // We don't set margin here because it breaks `size` in Chrome. We also\n // don't use `!important` on `size` as it breaks in Chrome.\n @page {\n size: $print-page-size;\n }\n body {\n min-width: $print-body-min-width !important;\n }\n .container {\n min-width: $print-body-min-width !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .badge {\n border: $border-width solid $black;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: $white !important;\n }\n }\n\n .table-bordered {\n th,\n td {\n border: 1px solid $gray-300 !important;\n }\n }\n\n .table-dark {\n color: inherit;\n\n th,\n td,\n thead th,\n tbody + tbody {\n border-color: $table-border-color;\n }\n }\n\n .table .thead-dark th {\n color: inherit;\n border-color: $table-border-color;\n }\n\n // Bootstrap specific changes end\n }\n}\n"]}
css/switchery.min.css CHANGED
@@ -1 +1 @@
1
- .switchery{background-color:#fff;border:1px solid #dfdfdf;border-radius:20px;cursor:pointer;display:inline-block;height:30px;position:relative;vertical-align:middle;width:50px;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;background-clip:content-box}.switchery>small{background:#fff;border-radius:100%;box-shadow:0 1px 3px rgba(0,0,0,.4);height:30px;position:absolute;top:0;width:30px}.switchery-small{border-radius:20px;height:20px;width:33px}.switchery-small>small{height:20px;width:20px}.switchery-large{border-radius:40px;height:40px;width:66px}.switchery-large>small{height:40px;width:40px}
1
+ .switchery{background-color:#fff;border:1px solid #dfdfdf;border-radius:20px;cursor:pointer;display:inline-block;height:30px;position:relative;vertical-align:middle;width:50px;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;background-clip:content-box}.switchery>small{background:#fff;border-radius:100%;box-shadow:0 1px 3px rgba(0,0,0,0.4);height:30px;position:absolute;top:0;width:30px}.switchery-small{border-radius:20px;height:20px;width:33px}.switchery-small>small{height:20px;width:20px}.switchery-large{border-radius:40px;height:40px;width:66px}.switchery-large>small{height:40px;width:40px}
css/themes/classic.css CHANGED
@@ -697,9 +697,7 @@ input#nifty_ratings_comment {
697
  float: left;
698
  display: block;
699
  height: 60px;
700
- padding-left: 10px;
701
  padding-right: 10px;
702
- width: 80px;
703
  }
704
 
705
  .wplc_hovercard_content_right {
697
  float: left;
698
  display: block;
699
  height: 60px;
 
700
  padding-right: 10px;
 
701
  }
702
 
703
  .wplc_hovercard_content_right {
css/themes/modern.css CHANGED
@@ -133,8 +133,7 @@
133
  /* max-height: 500px; */
134
  width: 368px;
135
  max-width: 100%;
136
- /* height: 80%; */
137
- top: 10%;
138
  border-top-left-radius: 15px;
139
  border-top-right-radius: 15px;
140
  box-shadow: 0 0 40px 0 rgba(150, 165, 190, .14);
@@ -207,7 +206,7 @@
207
  overflow: hidden;
208
  text-align: center;
209
  margin: 0 auto;
210
- padding: 16px;
211
  color: #fff;
212
  }
213
 
@@ -341,6 +340,7 @@
341
  text-align: center;
342
  padding: 16px;
343
  font-size: 12pt;
 
344
  }
345
 
346
  #wp-live-chat-inner-image-div {
@@ -602,9 +602,7 @@ span.tcx_pullup.up {
602
  float: left;
603
  display: block;
604
  /*height: 60px;*/
605
- padding-left: 10px;
606
  padding-right: 10px;
607
- width: 80px;
608
  font-weight: normal;
609
  }
610
 
@@ -625,10 +623,6 @@ span.tcx_pullup.up {
625
  border-radius: 30px;
626
  }
627
 
628
- #wplc_message_div {
629
- margin-top: 20px;
630
- }
631
-
632
  #wp-live-chat-2-inner #wplc_start_chat_btn {
633
  width: 100%;
634
  display: block;
133
  /* max-height: 500px; */
134
  width: 368px;
135
  max-width: 100%;
136
+ height: 70%;
 
137
  border-top-left-radius: 15px;
138
  border-top-right-radius: 15px;
139
  box-shadow: 0 0 40px 0 rgba(150, 165, 190, .14);
206
  overflow: hidden;
207
  text-align: center;
208
  margin: 0 auto;
209
+ padding: 4px 0px 16px 0px;
210
  color: #fff;
211
  }
212
 
340
  text-align: center;
341
  padding: 16px;
342
  font-size: 12pt;
343
+ margin-top: 20px;
344
  }
345
 
346
  #wp-live-chat-inner-image-div {
602
  float: left;
603
  display: block;
604
  /*height: 60px;*/
 
605
  padding-right: 10px;
 
606
  font-weight: normal;
607
  }
608
 
623
  border-radius: 30px;
624
  }
625
 
 
 
 
 
626
  #wp-live-chat-2-inner #wplc_start_chat_btn {
627
  width: 100%;
628
  display: block;
functions.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
  }
6
 
7
  $wplc_images='jpg|jpeg|png|gif|bmp';
@@ -77,6 +77,7 @@ function wplc_log_user_on_page($name,$email,$session, $is_mobile = false) {
77
  return $lastid;
78
 
79
  }
 
80
  function wplc_update_user_on_page($cid, $status = 5,$session) {
81
  global $wpdb;
82
  global $wplc_tblname_chats;
@@ -175,10 +176,9 @@ function wplc_record_chat_msg($from, $cid, $msg, $rest_check = false, $aid = fal
175
 
176
 
177
  if ($from == "2" && $rest_check == false) {
178
- $wplc_current_user = get_current_user_id();
179
-
180
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) ){
181
- } else { return "security issue"; }
182
  }
183
 
184
  if ($from == "1") {
@@ -207,19 +207,17 @@ function wplc_record_chat_msg($from, $cid, $msg, $rest_check = false, $aid = fal
207
  $msg = apply_filters("wplc_filter_message_control",$msg);
208
 
209
  if (!$aid) {
210
- $wplc_current_user = get_current_user_id();
211
-
212
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) ){
213
- $other_data = array('aid'=>$wplc_current_user);
214
- } else {
215
- $other_data = '';
216
- }
217
  } else {
218
- if( get_user_meta( $aid, 'wplc_ma_agent', true ) ){
219
- $other_data = array('aid'=>$aid);
220
- } else {
221
- $other_data = '';
222
- }
223
  }
224
 
225
  $wpdb->insert(
@@ -245,20 +243,8 @@ function wplc_record_chat_msg($from, $cid, $msg, $rest_check = false, $aid = fal
245
  '%s'
246
  )
247
  );
248
-
249
- $data = array(
250
- 'cid' => $cid,
251
- 'from' => $from,
252
- 'msg' => $orig_msg,
253
- 'orig' => $orig
254
- );
255
- //do_action("wplc_hook_message_sent",$data);
256
-
257
  wplc_update_active_timestamp(sanitize_text_field($cid));
258
-
259
-
260
  return true;
261
-
262
  }
263
 
264
  function wplc_update_active_timestamp($cid) {
@@ -405,40 +391,42 @@ add_filter("wplc_filter_list_chats_actions","wplc_filter_control_list_chats_acti
405
  * @version 6.0.04 Updated to ensure those with the correct access can access this function
406
  */
407
  function wplc_filter_control_list_chats_actions($actions,$result,$post_data) {
408
- $aid = apply_filters("wplc_filter_aid_in_action","");
409
-
410
- $wplc_current_user = get_current_user_id();
411
-
412
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) ){
 
 
 
413
 
414
- if (intval($result->status) == 2) {
415
- $url_params = "&action=ac&cid=".$result->id.$aid;
416
- $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
417
- $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">". apply_filters("wplc_accept_chat_button_filter", __("Accept Chat",'wp-live-chat-support'), $result->id)."</a>";
418
- }
419
- else if (intval($result->status) == 3 || intval($result->status) == 10) {
420
- $url_params = "&action=ac&cid=".$result->id.$aid;
421
- $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
422
- if ( !isset( $result->agent_id ) || $wplc_current_user == $result->agent_id ) { //Added backwards compat checks
423
- $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Open Chat",'wp-live-chat-support')."</a>";
424
- } else {
425
- $actions = "<span class=\"wplc-chat-in-progress\">" . __( "In progress with another agent", 'wp-live-chat-support') . "</span>";
426
- }
427
- }
428
- else if (intval($result->status) == 2) {
429
- $url_params = "&action=ac&cid=".$result->id.$aid;
430
- $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
431
- $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Accept Chat",'wp-live-chat-support')."</a>";
432
- }
433
- else if (intval($result->status) == 12 ) {
434
- $url_params = "&action=ac&cid=".$result->id.$aid;
435
- $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
436
- $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Open Chat",'wp-live-chat-support')."</a>";
437
  }
438
- } else {
439
- $actions = "<a href='#'>".__( 'Only chat agents can accept chats', 'wp-live-chat-support')."</a>";
 
 
 
 
 
 
 
 
 
 
 
440
  }
441
- return $actions;
 
 
 
442
  }
443
 
444
  function wplc_list_chats($post_data) {
@@ -704,7 +692,7 @@ function wplc_return_chat_messages($cid, $transcript = false, $html = true, $wpl
704
  } else if ($result->originates == 0 || $result->originates == 3) {
705
  $system_notification = true;
706
  $cuid = get_current_user_id();
707
- $is_agent = get_user_meta(intval( $cuid ), 'wplc_ma_agent', true);
708
  if ($is_agent && $result->originates == 3 ) {
709
  /* this user is an agent and the notification is meant for an agent, therefore display it */
710
  $display_notification = true;
@@ -886,8 +874,7 @@ function wplc_mark_as_read_agent_chat_messages($cid, $aid) {
886
  }
887
 
888
  function wplc_return_admin_chat_messages($cid) {
889
- $wplc_current_user = get_current_user_id();
890
- if (get_user_meta( $wplc_current_user, 'wplc_ma_agent', true)) {
891
  global $wpdb;
892
  global $wplc_tblname_msgs;
893
  /**
@@ -915,15 +902,12 @@ function wplc_return_admin_chat_messages($cid) {
915
  // system notifications from version 7
916
  $system_notification = true;
917
  }
918
-
919
  if (!$system_notification) {
920
  /* this is a normal message */
921
  if (function_exists('wplc_encrypt_decrypt_msg')) {
922
  $msg = wplc_encrypt_decrypt_msg($msg);
923
  }
924
-
925
  $msg_array = maybe_unserialize( $msg );
926
-
927
  if (is_array( $msg_array)) {
928
  $msg = $msg_array['m'];
929
  }
@@ -934,10 +918,9 @@ function wplc_return_admin_chat_messages($cid) {
934
  $msg_hist[$id]['msg'] = $msg;
935
  $msg_hist[$id]['originates'] = intval($result->originates);
936
  $msg_hist[$id]['other'] = $other_data;
937
-
938
  } else {
939
  /* add the system notification to the list */
940
- if ( isset( $msg_hist[$id] ) ) { $msg_hist[$id] = array(); }
941
  $msg_hist[$id]['msg'] = $msg;
942
  $msg_hist[$id]['other'] = $other_data;
943
  $msg_hist[$id]['originates'] = intval($result->originates);
@@ -956,31 +939,23 @@ function wplc_return_admin_chat_messages($cid) {
956
  * @return string "ok"
957
  */
958
  function wplc_mark_as_read_admin_chat_messages( $mid ) {
959
- $wplc_current_user = get_current_user_id();
960
-
961
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) ){
962
- global $wpdb;
963
- global $wplc_tblname_msgs;
964
-
965
- $wpdb->update(
966
- $wplc_tblname_msgs,
967
- array(
968
- 'status' => 1
969
- ),
970
- array('id' => $mid),
971
- array('%d'),
972
- array('%d')
973
- );
974
-
975
- } else { return "security issue"; }
976
-
977
  return "ok";
 
 
978
  }
979
 
980
-
981
-
982
-
983
-
984
  function wplc_return_chat_session_variable($cid) {
985
  global $wpdb;
986
  global $wplc_tblname_chats;
@@ -1731,33 +1706,29 @@ function wplc_advanced_settings_above_performance_control($wplc_settings) {
1731
  * Reverse of wplc_return_chat_id_by_rel
1732
  */
1733
  function wplc_return_chat_rel_by_id($cid) {
1734
- global $wpdb;
1735
- global $wplc_tblname_chats;
1736
-
1737
- $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `id` = %s LIMIT 1", $cid));
1738
- if ($results) {
1739
- foreach ($results as $result) {
1740
- if (isset($result->rel)) {
1741
- return $result->rel;
1742
- } else {
1743
- return $cid;
1744
- }
1745
- }
1746
- } else {
1747
  return $cid;
 
1748
  }
1749
-
 
 
1750
  }
1751
 
1752
  function wplc_all_avatars() {
1753
- $users = get_users(array(
1754
- 'meta_key' => 'wplc_ma_agent',
1755
- ));
1756
- $avatars = array();
1757
- foreach ($users as $user) {
1758
- $avatars[$user->data->ID] = wplc_get_avatar($user->data->ID);
1759
- }
1760
- return $avatars;
1761
  }
1762
 
1763
  function wplc_get_avatar($id) {
@@ -1846,43 +1817,19 @@ function wplc_display_chat_contents() {
1846
 
1847
  add_action("admin_init","wplc_control_logged_in_mrg");
1848
  function wplc_control_logged_in_mrg() {
1849
- $userid = get_current_user_id();
1850
- $checker = wplc_maa_check_if_user_is_agent($userid);
1851
- if ($checker !== "not_user_agent" && $checker > 0) {
1852
- update_user_meta($userid, "wplc_chat_agent_online", time());
1853
- }
1854
-
1855
  }
1856
 
1857
  add_action("init","wplc_control_logged_out_mrg");
1858
  function wplc_control_logged_out_mrg() {
1859
- if(!isset($_GET['role'])){
1860
- add_action('pre_get_users', 'wplc_advanced_access_manager_compatibility_mrg', 1000);
1861
- $check = get_users(array(
1862
- 'meta_key' => 'wplc_chat_agent_online',
1863
- ));
1864
-
1865
- if ($check) {
1866
- foreach ($check as $wplcuser) {
1867
- $check = get_user_meta($wplcuser->ID, "wplc_chat_agent_online");
1868
- if (isset($check[0])) {
1869
- $last_logged_in_time = $check[0];
1870
- if ($last_logged_in_time > 0) {
1871
- if ((time() - $last_logged_in_time) < 120) {
1872
- /* do nothing, they are online */
1873
- } else {
1874
- /* this user has not sent a heartbeat in over 120 seconds */
1875
- delete_user_meta($wplcuser->ID, "wplc_chat_agent_online");
1876
- }
1877
- }
1878
- }
1879
- }
1880
- } else {
1881
- return false;
1882
- }
1883
- } else {
1884
- return false;
1885
- }
1886
  }
1887
 
1888
  /**
@@ -1985,7 +1932,7 @@ function wplc_mrg_update_db( $networkwide = false ) {
1985
  $admins->add_cap('wplc_ma_agent');
1986
  $uid = get_current_user_id();
1987
  update_user_meta($uid, 'wplc_ma_agent', 1);
1988
- update_user_meta($uid, "wplc_chat_agent_online", time());
1989
  }
1990
 
1991
 
@@ -2100,7 +2047,7 @@ function wplc_quick_response_manage_number_column_mrg( $column, $post_id ) {
2100
  }
2101
 
2102
  function wplc_quick_response_add_agent_caps_mrg() {
2103
- if ( 'not_user_agent' !== wplc_ic_check_if_user_is_agent() ) {
2104
  $user_id = get_current_user_id();
2105
  $user = new WP_User($user_id);
2106
  $user->add_cap('edit_wplc_quick_response');
@@ -2362,10 +2309,9 @@ function wplc_choose_hook_control_chat_dashboard_above() {
2362
  if (!$wplc_settings['wplc_allow_agents_set_status']) {
2363
  return;
2364
  }
2365
- $status = wplc_get_agent_status(get_current_user_id());
2366
  ?>
2367
  <div class="wplc_admin_chat_switchery_a">
2368
- <input type="checkbox" class="wplc_switchery" name="wplc_agent_status" id="wplc_agent_status" <?php if ($status) { echo 'checked'; } ?> />
2369
  <div id="wplc_agent_status_text"></div>
2370
  </div>
2371
  <?php
@@ -2379,7 +2325,7 @@ function wplc_choose_hook_control_chat_dashboard_above() {
2379
  */
2380
  add_filter("wplc_filter_control_set_transient","wplc_choose_filter_control_set_set_transient",10,1);
2381
  function wplc_choose_filter_control_set_set_transient($set_transient) {
2382
- return wplc_get_agent_status(get_current_user_id());
2383
  }
2384
 
2385
  /**
@@ -2390,121 +2336,106 @@ function wplc_choose_filter_control_set_set_transient($set_transient) {
2390
  */
2391
  add_filter("wplc_final_loggedin_control","wplc_choose_final_loggedin_control",10,2);
2392
  function wplc_choose_final_loggedin_control($logged_in,$logged_in_via_app) {
2393
- /* get actuall logged in users and create an array to check with below */
2394
- add_action('pre_get_users', 'wplc_advanced_access_manager_compatibility_mrg', 1000);
2395
- $users = get_users(array('meta_key'=> 'wplc_chat_agent_online'));
2396
- $one_logged_in = false;
2397
-
2398
- foreach ($users as $wplc_user) {
2399
- $check = get_user_meta($wplc_user->ID,"wplc_chat_agent_online");
2400
- $logged_in = false;
2401
- if (!empty($check)) {
2402
- $last_logged_in_time = $check[0];
2403
- if ($last_logged_in_time > 0) {
2404
- if ((time() - $last_logged_in_time) < 70) {
2405
- $logged_in = true;
2406
- $one_logged_in = true;
2407
- }
2408
- }
2409
- }
2410
- if (!$logged_in) {
2411
- wplc_set_agent_status($wplc_user->ID, false);
2412
- }
2413
- }
2414
- return $one_logged_in;
2415
  }
2416
 
2417
  /**
2418
  * Latch onto the original callback for this plugin's ajax requests
2419
  * @return void
2420
  */
2421
- if (!function_exists("wplc_choose_hook_control_action_callback")) {
2422
- function wplc_choose_hook_control_action_callback() {
 
 
 
 
 
 
2423
 
2424
- if ($_POST['action'] == 'wplc_choose_accepting') {
2425
- $user_id = get_current_user_id();
2426
- wplc_set_agent_status($user_id, true);
2427
- do_action("wplc_hook_set_transient");
2428
- echo "done";
2429
- }
 
 
2430
 
2431
- if ($_POST['action'] == 'wplc_choose_not_accepting') {
2432
- $user_id = get_current_user_id();
2433
- wplc_set_agent_status($user_id, false);
2434
- delete_user_meta($user_id, "wplc_chat_agent_online");
2435
- delete_transient('wplc_is_admin_logged_in');
2436
- echo "done";
2437
- }
2438
 
2439
- if ($_POST['action'] == "wplc_typing") {
2440
- if (isset($_POST['cid']) && isset($_POST['user']) && isset($_POST['type'])) {
2441
- if((wplc_ic_check_if_user_is_agent() === "not_user_agent" && wplc_check_user_request($_POST['cid'])) || (wplc_ic_check_if_user_is_agent() !== "not_user_agent")){
2442
- echo wplc_typing_mrg(sanitize_text_field($_POST['user']), intval($_POST['cid']), sanitize_text_field($_POST['type']));
2443
- }
2444
  }
2445
  }
 
 
2446
 
2447
- if( $_POST['action'] == 'wplc_upload_file' ) {
2448
- $upload_dir = wp_upload_dir();
2449
- $user_dirname = $upload_dir['basedir'];
2450
- $cid=0;
2451
- $u_id_check=0;
2452
- if (isset($_POST['cid'])) {
2453
-
2454
- if(wplc_ic_check_if_user_is_agent() === "not_user_agent") {
2455
- if(wplc_check_user_request($_POST['cid'])){
2456
- $u_id_check = 1;
2457
- }
2458
- }else {
2459
- $u_id_check = 1;
2460
- }
2461
-
2462
- if($u_id_check === 1){
2463
- $cid = sanitize_text_field($_POST['cid']);
2464
- if( ! filter_var($cid, FILTER_VALIDATE_INT) ) {
2465
- /* We need to identify if this CID is a node CID, and if so, return the WP CID */
2466
- $cid = wplc_return_chat_id_by_rel($cid);
2467
- }
2468
-
2469
- $cid = intval($cid);
2470
-
2471
-
2472
- if( !file_exists( $user_dirname."/wp_live_chat/")) {
2473
- @mkdir($user_dirname.'/wp_live_chat/');
2474
- }
2475
-
2476
- if (!realpath($user_dirname."/wp_live_chat/" . $cid)) {
2477
- @mkdir( $user_dirname.'/wp_live_chat/'. $cid );
2478
- }
2479
-
2480
- if (isset($_FILES['file']) && isset($_POST['timestamp'])) {
2481
- $file_name = strtolower( sanitize_file_name($_FILES['file']['name']) );
2482
- $file_name = basename($file_name); //This prevents traversal
2483
- if (wplc_check_file_name_for_safe_extension($file_name) && wplc_check_file_mime_type($_FILES['file']['tmp_name'])) {
2484
- $upload_file_name = $file_name;
2485
- while (file_exists($user_dirname . "/wp_live_chat/" . $cid . "/" . $upload_file_name)) {
2486
- $upload_file_name = substr($file_name,0,strrpos($file_name, '.')).mt_rand(1000,9999).substr($file_name,strrpos($file_name, '.'));
2487
- }
2488
- if (move_uploaded_file($_FILES['file']['tmp_name'], $user_dirname."/wp_live_chat/" . $cid . "/" . $upload_file_name)) {
2489
- //File has been uploaded, let's now go ahead and check the mime type
2490
- $response = $upload_dir['baseurl']."/wp_live_chat/" . $cid . "/" . $upload_file_name;
2491
- echo $response;
2492
- } else {
2493
- echo "ERROR: Upload failed";
2494
- }
2495
- } else {
2496
- echo "ERROR: Security Violation";
2497
- }
2498
- }
2499
- }else {
2500
- echo "ERROR: Chat ID Tampering Detected.";
2501
- }
2502
- }else {
2503
- echo "ERROR: Upload failed. Invalid Chat ID.";
2504
- }
2505
- wp_die();
2506
  }
2507
- }
 
2508
  }
2509
 
2510
  function wplc_typing_mrg($user,$cid,$type) {
@@ -2556,13 +2487,17 @@ function wplc_choose_admin_scripts() {
2556
  'accepting_status' => __('Status (Online)', 'wp-live-chat-support'),
2557
  'accepting_chats' => __('Online', 'wp-live-chat-support'),
2558
  'not_accepting_chats' => __('Offline', 'wp-live-chat-support'),
2559
- 'not_accepting_status' => __('Status (Offline)', 'wp-live-chat-support')
 
 
2560
  );
 
2561
  wp_localize_script('wplc-choose-script', 'wplc_choose_admin_strings', $wpc_admin_js_strings);
 
2562
 
2563
  $wplc_current_user_id = get_current_user_id();
2564
 
2565
- if (wplc_get_agent_status($wplc_current_user_id)) {
2566
  /* user is online */
2567
  wp_localize_script('wplc-choose-script', 'wplc_choose_accept_chats', array('value'=>true));
2568
  } else {
@@ -2796,35 +2731,12 @@ function wplc_ic_filter_control_run_override($ret) {
2796
  * @return void
2797
  *
2798
  */
2799
- if (!function_exists("wplc_ic_filter_control_admin_javascript")) {
2800
- add_filter("wplc_filter_admin_javascript","wplc_ic_filter_control_admin_javascript");
2801
- function wplc_ic_filter_control_admin_javascript($data_array) {
2802
- $agent_id = wplc_ic_check_if_user_is_agent();
2803
- if ($agent_id) {
2804
- $data_array['agent_id'] = $agent_id;
2805
- }
2806
- return $data_array;
2807
-
2808
- }
2809
- }
2810
-
2811
- /**
2812
- * Check if the user is an agent
2813
- *
2814
- * @since 1.0.0
2815
- * @param
2816
- * @return string
2817
- *
2818
- */
2819
- if (!function_exists("wplc_ic_check_if_user_is_agent")) {
2820
- function wplc_ic_check_if_user_is_agent(){
2821
- $user_id = get_current_user_id();
2822
- if (sanitize_text_field(get_the_author_meta('wplc_ma_agent', $user_id ) ) === "1"){
2823
- return $user_id;
2824
- } else {
2825
- return "not_user_agent";
2826
- }
2827
- }
2828
  }
2829
 
2830
  /**
@@ -2951,20 +2863,14 @@ function wplc_hook_control_wplc_draw_chat_area($result) {
2951
  */
2952
  if (!function_exists("wplc_ma_hook_control_admin_meny_layout_display_top")) {
2953
  function wplc_ma_hook_control_admin_meny_layout_display_top() {
2954
- $wplc_current_user_id = get_current_user_id();
2955
- $is_agent = get_user_meta($wplc_current_user_id, 'wplc_ma_agent', true);
2956
- if(!$is_agent){
2957
- $warning = "<p style='color: red;'><b>".__('You are not a chat agent. Please make yourself a chat agent before trying to chat to visitors', 'wp-live-chat-support-multiple-agents')."</b></p>";
2958
- echo $warning;
2959
- }
2960
- return;
2961
  }
2962
  }
2963
 
2964
-
2965
-
2966
-
2967
-
2968
  /**
2969
  * Assign the chat to the agent
2970
  *
@@ -2992,29 +2898,6 @@ if (!function_exists("wplc_maa_update_agent_id")) {
2992
  }
2993
  }
2994
 
2995
-
2996
-
2997
- /**
2998
- * Check if the user is an agent
2999
- *
3000
- * @since 1.0.0
3001
- * @param
3002
- * @return string
3003
- *
3004
- */
3005
- if (!function_exists("wplc_maa_check_if_user_is_agent")) {
3006
- function wplc_maa_check_if_user_is_agent(){
3007
- $user_id = get_current_user_id();
3008
- if (sanitize_text_field(get_the_author_meta('wplc_ma_agent', $user_id ) ) == "1"){
3009
- return $user_id;
3010
- } else {
3011
- return "not_user_agent";
3012
- }
3013
- }
3014
- }
3015
-
3016
-
3017
-
3018
  /**
3019
  * Check if the chat has been answered by another chat agent
3020
  * @since 1.0.0
@@ -3090,7 +2973,7 @@ if (!function_exists("wplc_ma_first_time_install")) {
3090
  $admins->add_cap('wplc_ma_agent');
3091
  $uid = get_current_user_id();
3092
  update_user_meta($uid, 'wplc_ma_agent', 1);
3093
- update_user_meta($uid, "wplc_chat_agent_online", time());
3094
  }
3095
  }
3096
 
@@ -3118,8 +3001,8 @@ if (!function_exists("wplc_maa_set_user_as_agent")) {
3118
 
3119
  if ($_POST['wplc_ma_agent'] == '1') {
3120
  $wplc_ma_user = new WP_User( $user_id );
3121
- $wplc_ma_user->add_cap( 'wplc_ma_agent' );
3122
- update_user_meta($user_id, "wplc_chat_agent_online", time());
3123
  } else {
3124
  $wplc_ma_user = new WP_User( $user_id );
3125
  $wplc_ma_user->remove_cap( 'wplc_ma_agent' );
@@ -3400,20 +3283,17 @@ if (!function_exists("wplc_ma_hook_control_accept_chat_url")) {
3400
  }
3401
  }
3402
 
3403
-
3404
  if (!function_exists("wplc_filter_control_aid_in_action")) {
3405
- add_filter("wplc_filter_aid_in_action","wplc_filter_control_aid_in_action");
3406
- function wplc_filter_control_aid_in_action() {
3407
- $aid = "";
3408
- $agent_id = wplc_maa_check_if_user_is_agent();
3409
- if(is_numeric($agent_id)){
3410
- $aid = "&aid=".$agent_id;
3411
- }
3412
- return $aid;
3413
- }
3414
  }
3415
 
3416
-
3417
  /**
3418
  *
3419
  *
@@ -3425,19 +3305,13 @@ if (!function_exists("wplc_filter_control_aid_in_action")) {
3425
  if (!function_exists("wplc_ma_filter_control_admin_javascript")) {
3426
  add_filter("wplc_filter_admin_javascript","wplc_ma_filter_control_admin_javascript");
3427
  function wplc_ma_filter_control_admin_javascript($data_array) {
3428
- $agent_id = wplc_maa_check_if_user_is_agent();
3429
- if ($agent_id) {
3430
- $data_array['agent_id'] = $agent_id;
3431
- }
3432
- return $data_array;
3433
-
3434
  }
3435
  }
3436
 
3437
-
3438
-
3439
-
3440
-
3441
  /**
3442
  * Control the content below the visitor count
3443
  * @return void
@@ -3445,35 +3319,12 @@ if (!function_exists("wplc_ma_filter_control_admin_javascript")) {
3445
  if (!function_exists("wplc_ma_filter_control_chat_dashboard_visitors_online_bottom")) {
3446
  add_action("wplc_filter_chat_dahsboard_visitors_online_bottom","wplc_ma_filter_control_chat_dashboard_visitors_online_bottom",11);
3447
  function wplc_ma_filter_control_chat_dashboard_visitors_online_bottom($text) {
3448
- $text = " <span class='wplc_agents_online'>".wplc_maa_total_agents_online()."</span> ";
3449
  $text .= __("Agent(s) online",'wp-live-chat-support');
3450
  return $text;
3451
  }
3452
  }
3453
 
3454
- /**
3455
- * Count how many agents are online
3456
- * @return int number of agents
3457
- */
3458
- function wplc_maa_total_agents_online() {
3459
- $user_array = get_users(array(
3460
- 'meta_key'=> 'wplc_chat_agent_online',
3461
- ));
3462
- $wplc_settings = wplc_get_options();
3463
- if ($wplc_settings['wplc_allow_agents_set_status']) {
3464
- $agent_status = wplc_get_all_agent_status();
3465
- $count = 0;
3466
- foreach($user_array as $v) {
3467
- if (isset($agent_status[$v->ID]) && $agent_status[$v->ID]) {
3468
- $count++;
3469
- }
3470
- }
3471
- return $count;
3472
- } else {
3473
- return count($user_array);
3474
- }
3475
- }
3476
-
3477
  add_action('admin_bar_menu', 'wplc_maa_online_agents', 100);
3478
  function wplc_maa_online_agents() {
3479
  if (!current_user_can('wplc_ma_agent', array(null))) {
@@ -3494,9 +3345,27 @@ function wplc_maa_online_agents() {
3494
  .wplc_green_circle{
3495
  background:rgb(103, 213, 82);
3496
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3497
  </style>
3498
  <?php
3499
- $agent_count = wplc_maa_total_agents_online();
 
3500
  if ($agent_count>0) {
3501
  $circle_class = "wplc_green_circle";
3502
  if ($agent_count==1) {
@@ -3512,22 +3381,28 @@ function wplc_maa_online_agents() {
3512
  global $wp_admin_bar;
3513
  $wp_admin_bar->add_menu( array(
3514
  'id' => 'wplc_ma_online_agents',
3515
- 'title' => '<span class="wplc_circle '.$circle_class.'" id="wplc_ma_online_agents_circle"></span><span id="wplc_ma_online_agents_count">'.$agent_count.'</span> '.$chat_agents,
3516
  'href' => false
3517
  ));
3518
 
3519
- if ($agent_count > 0) {
3520
- $user_array = get_users(array('meta_key'=> 'wplc_chat_agent_online'));
3521
- foreach($user_array as $user) {
3522
- if (wplc_get_agent_status($user->ID)) {
3523
- $wp_admin_bar->add_menu(array(
3524
- 'id' => 'wplc_user_online_'.$user->ID,
3525
- 'parent' => 'wplc_ma_online_agents',
3526
- 'title' => $user->display_name,
3527
- 'href' => false,
3528
- ));
3529
- }
3530
- }
 
 
 
 
 
 
3531
  }
3532
  }
3533
 
@@ -3569,7 +3444,7 @@ if (!function_exists("wplc_maa_hook_control_head")) {
3569
  if (!function_exists("wplc_maa_filter_control_check_if_logged_in")) {
3570
  add_filter("wplc_filter_is_admin_logged_in","wplc_maa_filter_control_check_if_logged_in",10,1);
3571
  function wplc_maa_filter_control_check_if_logged_in($logged_in) {
3572
- $logged_in['site'] = wplc_maa_is_agent_online();
3573
  return $logged_in;
3574
  }
3575
  }
@@ -3583,21 +3458,10 @@ if (!function_exists("wplc_maa_filter_control_check_if_logged_in")) {
3583
  if (!function_exists("wplc_maa_agent_logout")) {
3584
  add_action('wp_logout', 'wplc_maa_agent_logout');
3585
  function wplc_maa_agent_logout(){
3586
- $user_id = get_current_user_id();
3587
- delete_user_meta($user_id, "wplc_chat_agent_online");
3588
  }
3589
  }
3590
 
3591
- /**
3592
- * Is there at least one agent online?
3593
- * @return bool
3594
- * @since 1.0.00
3595
- */
3596
-
3597
- function wplc_maa_is_agent_online() {
3598
- return wplc_maa_total_agents_online()>0;
3599
- }
3600
-
3601
  /**
3602
  * Add the JS file to the admin screen
3603
  * @return void
@@ -3624,20 +3488,18 @@ if (!function_exists("wplc_control_admin_javascript")) {
3624
  do_action("wplc_maa_hook_head");
3625
  }
3626
 
3627
- if (!function_exists("wplc_ma_hook_control_action_callback")) {
3628
- add_action("wplc_hook_set_transient","wplc_ma_hook_control_set_transient",9);
3629
- function wplc_ma_hook_control_set_transient() {
3630
- $should_set_transient = apply_filters("wplc_filter_control_set_transient",true);
3631
- if ($should_set_transient) {
3632
- if (isset($_POST['user_id'])) { $user_id = sanitize_text_field($_POST['user_id']); } else { $user_id = get_current_user_id(); }
3633
- wplc_maa_set_agents_online($user_id);
3634
- }
3635
- remove_action("wplc_hook_set_transient","wplc_hook_control_set_transient");
3636
-
3637
- }
3638
  }
3639
 
3640
-
3641
  if (!function_exists("wplc_ma_hook_control_remove_transient")) {
3642
  add_action("wplc_hook_remove_transient","wplc_ma_hook_control_remove_transient",9);
3643
  function wplc_ma_hook_control_remove_transient() {
@@ -3651,91 +3513,82 @@ if (!function_exists("wplc_ma_hook_control_remove_transient")) {
3651
  * @return void
3652
  * @since 1.0.00
3653
  */
3654
- if (!function_exists("wplc_ma_hook_control_action_callback")) {
3655
- add_action("wplc_hook_action_callback","wplc_ma_hook_control_action_callback");
3656
- function wplc_ma_hook_control_action_callback() {
3657
-
3658
- if ($_POST['action'] == "wplc_add_agent") {
3659
- if (current_user_can("manage_options")) {
3660
- $uid = sanitize_text_field(intval($_POST['uid']));
3661
- if (isset($uid)) {
3662
- update_user_meta($uid, 'wplc_ma_agent', true);
3663
- echo "1";
3664
- } else {
3665
- echo "0";
3666
- }
3667
- }
3668
- }
3669
- if ($_POST['action'] == "wplc_remove_agent") {
3670
- if (current_user_can("manage_options")) {
3671
- $uid = sanitize_text_field(intval($_POST['uid']));
3672
- if (isset($uid)) {
3673
- delete_user_meta($uid, 'wplc_ma_agent');
3674
- echo "1";
3675
- } else {
3676
- echo "0";
3677
- }
3678
- }
3679
- }
3680
-
3681
- if ($_POST['action'] == "wplc_macro") {
3682
- if(wplc_ic_check_if_user_is_agent() !== "not_user_agent") {
3683
- if (isset($_POST['postid'])) {
3684
- $post_id = sanitize_text_field($_POST['postid']);
3685
- } else {
3686
- return false;
3687
- }
3688
 
3689
- if ($post_id > 0) {
3690
- $post_details = get_post($post_id);
3691
- if ($post_details) {
3692
- echo json_encode(nl2br($post_details->post_content));
3693
- } else {
3694
- echo json_encode("No post with that ID");
3695
- die();
3696
- }
3697
- } else {
3698
- echo json_encode("No macro with that ID");
3699
- die();
3700
- }
3701
- }else {
3702
- echo json_encode("You do not have permission to perform this action.");
3703
- die();
3704
- }
3705
  }
 
 
 
 
 
 
 
 
 
3706
 
3707
- if( $_POST['action'] == 'wplc_record_chat_rating' ){
3708
- $rating_id = sanitize_text_field($_POST['cid']);
3709
- $rating_score = sanitize_text_field($_POST['rating']);
3710
- $u_id_check=0;
3711
-
3712
- if(wplc_check_user_request($_POST['cid'])){
3713
- $u_id_check = 1;
3714
- }
3715
-
3716
- if($u_id_check === 1){
3717
-
3718
- if( ! filter_var($rating_id, FILTER_VALIDATE_INT) ) {
3719
- /* We need to identify if this CID is a node CID, and if so, return the WP CID */
3720
- $rating_id = wplc_return_chat_id_by_rel($rating_id);
3721
- }
3722
-
3723
-
3724
- $nifty_record_rating = nifty_record_rating_mrg($rating_id, $rating_score);
3725
- if ($nifty_record_rating) {
3726
- echo 'rating added';
3727
- wp_die();
3728
- } else {
3729
- echo "There was an error sending your chat message. Please contact support";
3730
- wp_die();
3731
- }
3732
- }else {
3733
- echo "There was an error sending your chat rating. Please contact support";
3734
- wp_die();
3735
- }
3736
- }
3737
-
3738
- }
3739
  }
3740
 
3741
  /**
@@ -3743,28 +3596,13 @@ if (!function_exists("wplc_ma_hook_control_action_callback")) {
3743
  * @return void
3744
  * @since 1.0.00
3745
  */
3746
-
3747
- if (!function_exists("wplc_maa_set_agents_online")) {
3748
- function wplc_maa_set_agents_online($user_id){
3749
-
3750
- if (sanitize_text_field( get_the_author_meta( 'wplc_ma_agent', $user_id ) ) == "1"){
3751
-
3752
- update_user_meta($user_id, "wplc_chat_agent_online", time());
3753
- }
3754
- $users = get_users(array(
3755
- 'meta_key'=> 'wplc_chat_agent_online',
3756
- ));
3757
- foreach($users as $user){
3758
- $time = get_user_meta($user->ID, "wplc_chat_agent_online", true);
3759
- $diff = time() - $time;
3760
- if($diff > 125){
3761
- delete_user_meta($user->ID, "wplc_chat_agent_online");
3762
- }
3763
- }
3764
- }
3765
  }
3766
 
3767
-
3768
  /* WPLC Social Icons Filter*/
3769
  // add_filter("wplc_filter_chat_header_above","wplc_chat_social_div_mrg",5,2);
3770
  // add_filter("wplc_filter_chat_4th_layer_below_input","wplc_chat_social_div_mrg",5,2);
@@ -3992,128 +3830,64 @@ function wplc_reporting_tabs_filter_experience_ratings_control_mrg($tabs_array){
3992
 
3993
 
3994
  add_filter('wplc_reporting_tab_content', 'wplc_reporting_tab_content_filter_experience_ratings_control_mrg', 10, 1);
3995
- function wplc_reporting_tab_content_filter_experience_ratings_control_mrg($tabs_array){
3996
- $ratings = "<h3>".__("Agent Statistics", 'wp-live-chat-support')."</h3>";
3997
-
3998
- $user_array = get_users(array(
3999
- 'meta_key' => 'wplc_ma_agent',
4000
- ));
4001
-
4002
- $ratings .= "<style>";
4003
- $ratings .= ".wplc_agent_grav_report { display:inline-block; }";
4004
- $ratings .= ".wplc_agent_card_details { display:inline-block; margin-left: 5px;}";
4005
- $ratings .= ".wplc_agent_card { width:100%; }";
4006
- $ratings .= ".wplc_agent_container {
4007
- width: 30%;
4008
- padding: 5px;
4009
- border-radius: 7px;
4010
- box-shadow: 0px 0px 5px 2px #9999992b;
4011
- display: inline-block;
4012
- margin-right: 13px;
4013
- vertical-align: top;
4014
- margin-bottom:10px;
4015
- }";
4016
- $ratings .= ".wplc_agent_data {
4017
- max-height: 200px;
4018
- overflow-y: auto;
4019
- padding: 5px;
4020
- border: 1px lightgrey solid;
4021
- }";
4022
- $ratings .= "</style>";
4023
-
4024
- $hist_nonce = wp_create_nonce('wplc_history_nonce');
4025
-
4026
- if ($user_array) {
4027
-
4028
- foreach ($user_array as $user) {
4029
-
4030
- $ratings .= "<div class='wplc_agent_container'>";
4031
- $rating_stats = nifty_get_rating_report_mrg($user->ID);
4032
-
4033
- $ratings .= "<div class='wplc_agent_card'>";
4034
- $ratings .= "<img class='wplc_agent_grav_report' src=\"//www.gravatar.com/avatar/" . md5($user->user_email) . "?s=80&d=mm\" />";
4035
- $ratings .= "<div class='wplc_agent_card_details'>";
4036
- $ratings .= "<strong>" . $user->display_name . "</strong><br>";
4037
- $ratings .= "<small>" . $user->user_email . "</small><br>";
4038
- $ratings .= "<hr>";
4039
- $ratings .= "<small><strong>".__("Satisfaction Rating", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "--" : $rating_stats['percentage'] ). "%</small><br>";
4040
- $ratings .= "<small><strong>".__("Rating Count", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['total_ratings'])." (".__("Good",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['good_count']). " || ".__("Bad",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['bad_count']). ")</small>";
4041
- $ratings .= "</div>";
4042
- $ratings .= "</div>";
4043
-
4044
- /** Removed as of 07-2019 */
4045
- /*$ratings .= "<div class='wplc_agent_data'>";
4046
-
4047
- if(is_bool($rating_stats) && $rating_stats == false){
4048
- $ratings .= "<div style='width:90%;display: inline-block; min-height: 30px;'>";
4049
- $ratings .= "<i>".__("No Ratings for this agent", 'wp-live-chat-support')."</i>";
4050
- $ratings .= "</div>";
4051
- }else{
4052
- $ratings_for_agent = $rating_stats[$user->ID];
4053
- foreach ($ratings_for_agent as $id => $rate) {
4054
- $cid = $rate['cid'];
4055
- $date = substr($rate['time'], 0, strpos($rate['time'], ' '));
4056
- $ratings .= "<div style='width:70%;display: inline-block; min-height: 30px;'>";
4057
- $ratings .= "<small style='display:inline-block; height: unset'>$date</small>" . " - <strong style='".(intval($rate['rating']) == 1 ? "color:#439134;": "color:#ac1d1d;")."'>".(intval($rate['rating']) == 1 ? __("Good", 'wp-live-chat-support') : __("Bad", 'wp-live-chat-support') )."</strong>";
4058
- $ratings .= " - <i style='width:auto;'>\"" . $rate['comment'] . "\"</i>";
4059
- $ratings .= "</div>";
4060
- $ratings .= " <a style='float:right' class='button' href='?page=wplivechat-menu&action=history&cid=".$cid."&wplc_history_nonce=" . $hist_nonce . "' target='_blank'>" . __("View", 'wp-live-chat-support') . "</a>";
4061
-
4062
- }
4063
- }
4064
-
4065
- $ratings .= "</div>";*/
4066
- $ratings .= "</div>";
4067
-
4068
- }
4069
-
4070
- $rating_stats = nifty_get_rating_report_mrg(0);
4071
- if(!empty($rating_stats[0]) && $rating_stats[0] !== false){
4072
- $ratings .= "<div class='wplc_agent_container'>";
4073
- $ratings .= "<div class='wplc_agent_card'>";
4074
- $ratings .= "<div class='wplc_agent_card_details'>";
4075
- $ratings .= "<strong>No Agent</strong><br>";
4076
- $ratings .= "<small>Reviewed before agent joined, or with multiple agents</small><br>";
4077
- $ratings .= "<hr>";
4078
- $ratings .= "<small><strong>".__("Satisfaction Rating", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "--" : $rating_stats['percentage'] ). "%</small><br>";
4079
- $ratings .= "<small><strong>".__("Rating Count", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['total_ratings'])." (".__("Good",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['good_count']). " || ".__("Bad",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['bad_count']). ")</small>";
4080
- $ratings .= "</div>";
4081
- $ratings .= "</div>";
4082
-
4083
- /** Removed as of 07-2019*/
4084
- /*
4085
- $ratings .= "<div class='wplc_agent_data'>";
4086
-
4087
- if(is_bool($rating_stats) && $rating_stats == false){
4088
- $ratings .= "<div style='width:90%;display: inline-block; min-height: 30px;'>";
4089
- $ratings .= "<i>".__("No Ratings for this agent", 'wp-live-chat-support')."</i>";
4090
- $ratings .= "</div>";
4091
- }else{
4092
- $ratings_for_agent = $rating_stats[0];
4093
- foreach ($ratings_for_agent as $id => $rate) {
4094
- $cid = $rate['cid'];
4095
- $date = substr($rate['time'], 0, strpos($rate['time'], ' '));
4096
-
4097
- $ratings .= "<div style='width:70%;display: inline-block; min-height: 30px;'>";
4098
- $ratings .= "<small style='display:inline-block; height: unset'>$date</small>" . " - <strong style='".(intval($rate['rating']) == 1 ? "color:#439134;": "color:#ac1d1d;")."'>".(intval($rate['rating']) == 1 ? __("Good", 'wp-live-chat-support') : __("Bad", 'wp-live-chat-support') )."</strong>";
4099
- $ratings .= " - <i style='width:auto;'>\"" . $rate['comment'] . "\"</i>";
4100
- $ratings .= "</div>";
4101
- $ratings .= " <a style='float:right' class='button' href='?page=wplivechat-menu&action=history&cid=".$cid."&wplc_history_nonce=" . $hist_nonce . "' target='_blank'>" . __("View", 'wp-live-chat-support') . "</a>";
4102
-
4103
- }
4104
- }
4105
-
4106
- $ratings .= "</div>";
4107
- */
4108
- $ratings .= "</div>";
4109
- }
4110
 
4111
- }
4112
-
4113
-
 
 
 
 
 
 
 
 
 
 
 
4114
 
4115
- $tabs_array['ux_ratings'] = $ratings;
4116
- return $tabs_array;
4117
  }
4118
 
4119
  add_action('admin_enqueue_scripts', 'wplc_reporting_scripts_mrg');
@@ -4746,7 +4520,7 @@ add_action('wplc_hook_initiate_chat', 'wplc_mrg_chat_notification_extender', 99,
4746
  function wplc_register_common_node() {
4747
  global $wplc_allowed_extensions;
4748
  $wplc_settings = wplc_get_options();
4749
- wp_register_script('wplc-admin-js-agent-common', WPLC_PLUGIN_URL.'/js/wplc_common_node.js', null, WPLC_PLUGIN_VERSION, false);
4750
  $current_user=wp_get_current_user();
4751
  $date_days=array();
4752
  for($i=0;$i<7;$i++) {
@@ -5155,9 +4929,149 @@ function wplc_cleanup_old_options($wplc_settings) {
5155
  return $wplc_settings;
5156
  }
5157
 
5158
- function wplc_get_agent_status($uid) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5159
  $wplc_settings = wplc_get_options();
5160
- $choose_array = wplc_get_all_agent_status();
5161
  if (!isset($choose_array[$uid])) {
5162
  $choose_array[$uid]=true;
5163
  update_option("WPLC_CHOOSE_ACCEPTING", $choose_array);
@@ -5169,15 +5083,15 @@ function wplc_get_agent_status($uid) {
5169
  return $choose_array[$uid];
5170
  }
5171
 
5172
- function wplc_set_agent_status($uid,$online) {
5173
- $choose_array = wplc_get_all_agent_status();
5174
  if (!isset($choose_array[$uid]) || $choose_array[$uid]!=boolval($online)) {
5175
  $choose_array[$uid]=boolval($online);
5176
  update_option("WPLC_CHOOSE_ACCEPTING", $choose_array);
5177
  }
5178
  }
5179
 
5180
- function wplc_get_all_agent_status() {
5181
  $choose_array = get_option("WPLC_CHOOSE_ACCEPTING");
5182
  if (!is_array($choose_array)) {
5183
  $choose_array = array();
@@ -5185,36 +5099,10 @@ function wplc_get_all_agent_status() {
5185
  return $choose_array;
5186
  }
5187
 
5188
- function wplc_ajax_generate_new_tokens() {
5189
- if (isset($_POST['action']) && ($_POST['action'] === "wplc_generate_new_node_token" || $_POST['action'] === "wplc_new_secret_key") && isset($_POST['nonce']) && wplc_maa_check_if_user_is_agent() !== "not_user_agent") {
5190
-
5191
- $nonce = $_POST['nonce'];
5192
- $action = $_POST['action'];
5193
- $error = false;
5194
-
5195
- if($action === "wplc_generate_new_node_token") {
5196
- if(wp_verify_nonce( $nonce, 'generate_new_token')) {
5197
- $res = wplc_node_server_token_get(true);
5198
- echo $res;
5199
- }else {
5200
- $error = true;
5201
- }
5202
- }elseif ($action === "wplc_new_secret_key") {
5203
- if(wp_verify_nonce( $nonce, 'generate_new_secret_token')) {
5204
- $user_token = wplc_api_s_key_create();
5205
- update_option("wplc_api_secret_token", $user_token);
5206
- echo $user_token;
5207
- }else {
5208
- $error = true;
5209
- }
5210
- }
5211
-
5212
- if($error === true){
5213
- _e("You do not have permission to perform this action",'wp-live-chat-support');
5214
- }
5215
-
5216
- }else {
5217
- _e("You do not have permission to perform this action",'wp-live-chat-support');
5218
- }
5219
- wp_die();
5220
- }
1
  <?php
2
 
3
  if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
  }
6
 
7
  $wplc_images='jpg|jpeg|png|gif|bmp';
77
  return $lastid;
78
 
79
  }
80
+
81
  function wplc_update_user_on_page($cid, $status = 5,$session) {
82
  global $wpdb;
83
  global $wplc_tblname_chats;
176
 
177
 
178
  if ($from == "2" && $rest_check == false) {
179
+ if (!wplc_user_is_agent()) {
180
+ return "security issue";
181
+ }
 
182
  }
183
 
184
  if ($from == "1") {
207
  $msg = apply_filters("wplc_filter_message_control",$msg);
208
 
209
  if (!$aid) {
210
+ if (wplc_user_is_agent()) {
211
+ $other_data = array('aid'=>get_current_user_id());
212
+ } else {
213
+ $other_data = '';
214
+ }
 
 
215
  } else {
216
+ if (wplc_user_is_agent($aid)) {
217
+ $other_data = array('aid'=>$aid);
218
+ } else {
219
+ $other_data = '';
220
+ }
221
  }
222
 
223
  $wpdb->insert(
243
  '%s'
244
  )
245
  );
 
 
 
 
 
 
 
 
 
246
  wplc_update_active_timestamp(sanitize_text_field($cid));
 
 
247
  return true;
 
248
  }
249
 
250
  function wplc_update_active_timestamp($cid) {
391
  * @version 6.0.04 Updated to ensure those with the correct access can access this function
392
  */
393
  function wplc_filter_control_list_chats_actions($actions,$result,$post_data) {
394
+ $aid = apply_filters("wplc_filter_aid_in_action","");
395
+ if (wplc_user_is_agent()) {
396
+ switch (intval($result->status)) {
397
+ case 2:
398
+ $url_params = "&action=ac&cid=".$result->id.$aid;
399
+ $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
400
+ $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">". apply_filters("wplc_accept_chat_button_filter", __("Accept Chat",'wp-live-chat-support'), $result->id)."</a>";
401
+ break;
402
 
403
+ case 3:
404
+ case 10:
405
+ $url_params = "&action=ac&cid=".$result->id.$aid;
406
+ $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
407
+ if (!isset( $result->agent_id ) || get_current_user_id() == $result->agent_id ) { //Added backwards compat checks
408
+ $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Open Chat",'wp-live-chat-support')."</a>";
409
+ } else {
410
+ $actions = "<span class=\"wplc-chat-in-progress\">" . __( "In progress with another agent", 'wp-live-chat-support') . "</span>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  }
412
+ break;
413
+
414
+ case 2:
415
+ $url_params = "&action=ac&cid=".$result->id.$aid;
416
+ $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
417
+ $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Accept Chat",'wp-live-chat-support')."</a>";
418
+ break;
419
+
420
+ case 12:
421
+ $url_params = "&action=ac&cid=".$result->id.$aid;
422
+ $url = admin_url( 'admin.php?page=wplivechat-menu'.$url_params);
423
+ $actions = "<a href=\"".$url."\" class=\"wplc_open_chat button button-primary\" window-title=\"WP_Live_Chat_".$result->id."\">".__("Open Chat",'wp-live-chat-support')."</a>";
424
+ break;
425
  }
426
+ } else {
427
+ $actions = "<a href='#'>".__( 'Only chat agents can accept chats', 'wp-live-chat-support')."</a>";
428
+ }
429
+ return $actions;
430
  }
431
 
432
  function wplc_list_chats($post_data) {
692
  } else if ($result->originates == 0 || $result->originates == 3) {
693
  $system_notification = true;
694
  $cuid = get_current_user_id();
695
+ $is_agent = wplc_user_is_agent($cuid);
696
  if ($is_agent && $result->originates == 3 ) {
697
  /* this user is an agent and the notification is meant for an agent, therefore display it */
698
  $display_notification = true;
874
  }
875
 
876
  function wplc_return_admin_chat_messages($cid) {
877
+ if (wplc_user_is_agent()) {
 
878
  global $wpdb;
879
  global $wplc_tblname_msgs;
880
  /**
902
  // system notifications from version 7
903
  $system_notification = true;
904
  }
 
905
  if (!$system_notification) {
906
  /* this is a normal message */
907
  if (function_exists('wplc_encrypt_decrypt_msg')) {
908
  $msg = wplc_encrypt_decrypt_msg($msg);
909
  }
 
910
  $msg_array = maybe_unserialize( $msg );
 
911
  if (is_array( $msg_array)) {
912
  $msg = $msg_array['m'];
913
  }
918
  $msg_hist[$id]['msg'] = $msg;
919
  $msg_hist[$id]['originates'] = intval($result->originates);
920
  $msg_hist[$id]['other'] = $other_data;
 
921
  } else {
922
  /* add the system notification to the list */
923
+ if ( isset( $msg_hist[$id] ) ) { $msg_hist[$id] = array(); }
924
  $msg_hist[$id]['msg'] = $msg;
925
  $msg_hist[$id]['other'] = $other_data;
926
  $msg_hist[$id]['originates'] = intval($result->originates);
939
  * @return string "ok"
940
  */
941
  function wplc_mark_as_read_admin_chat_messages( $mid ) {
942
+ if (wplc_user_is_agent()) {
943
+ global $wpdb;
944
+ global $wplc_tblname_msgs;
945
+ $wpdb->update(
946
+ $wplc_tblname_msgs,
947
+ array(
948
+ 'status' => 1
949
+ ),
950
+ array('id' => $mid),
951
+ array('%d'),
952
+ array('%d')
953
+ );
 
 
 
 
 
 
954
  return "ok";
955
+ }
956
+ return "security issue";
957
  }
958
 
 
 
 
 
959
  function wplc_return_chat_session_variable($cid) {
960
  global $wpdb;
961
  global $wplc_tblname_chats;
1706
  * Reverse of wplc_return_chat_id_by_rel
1707
  */
1708
  function wplc_return_chat_rel_by_id($cid) {
1709
+ global $wpdb;
1710
+ global $wplc_tblname_chats;
1711
+ $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `id` = %s LIMIT 1", $cid));
1712
+ if ($results) {
1713
+ foreach ($results as $result) {
1714
+ if (isset($result->rel)) {
1715
+ return $result->rel;
1716
+ } else {
 
 
 
 
 
1717
  return $cid;
1718
+ }
1719
  }
1720
+ } else {
1721
+ return $cid;
1722
+ }
1723
  }
1724
 
1725
  function wplc_all_avatars() {
1726
+ $users = wplc_get_agent_users();
1727
+ $avatars = array();
1728
+ foreach ($users as $user) {
1729
+ $avatars[$user->data->ID] = wplc_get_avatar($user->data->ID);
1730
+ }
1731
+ return $avatars;
 
 
1732
  }
1733
 
1734
  function wplc_get_avatar($id) {
1817
 
1818
  add_action("admin_init","wplc_control_logged_in_mrg");
1819
  function wplc_control_logged_in_mrg() {
1820
+ if (wplc_user_is_agent()) {
1821
+ wplc_update_agent_time();
1822
+ }
 
 
 
1823
  }
1824
 
1825
  add_action("init","wplc_control_logged_out_mrg");
1826
  function wplc_control_logged_out_mrg() {
1827
+ if (!isset($_GET['role'])) {
1828
+ add_action('pre_get_users', 'wplc_advanced_access_manager_compatibility_mrg', 1000);
1829
+ wplc_check_agents_timeout();
1830
+ } else {
1831
+ return false;
1832
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1833
  }
1834
 
1835
  /**
1932
  $admins->add_cap('wplc_ma_agent');
1933
  $uid = get_current_user_id();
1934
  update_user_meta($uid, 'wplc_ma_agent', 1);
1935
+ wplc_update_agent_time($uid);
1936
  }
1937
 
1938
 
2047
  }
2048
 
2049
  function wplc_quick_response_add_agent_caps_mrg() {
2050
+ if (wplc_user_is_agent()) {
2051
  $user_id = get_current_user_id();
2052
  $user = new WP_User($user_id);
2053
  $user->add_cap('edit_wplc_quick_response');
2309
  if (!$wplc_settings['wplc_allow_agents_set_status']) {
2310
  return;
2311
  }
 
2312
  ?>
2313
  <div class="wplc_admin_chat_switchery_a">
2314
+ <input type="checkbox" class="wplc_switchery" name="wplc_agent_status" id="wplc_agent_status" <?php if (wplc_get_agent_accepting(get_current_user_id())) { echo 'checked'; } ?> />
2315
  <div id="wplc_agent_status_text"></div>
2316
  </div>
2317
  <?php
2325
  */
2326
  add_filter("wplc_filter_control_set_transient","wplc_choose_filter_control_set_set_transient",10,1);
2327
  function wplc_choose_filter_control_set_set_transient($set_transient) {
2328
+ return wplc_get_agent_accepting(get_current_user_id());
2329
  }
2330
 
2331
  /**
2336
  */
2337
  add_filter("wplc_final_loggedin_control","wplc_choose_final_loggedin_control",10,2);
2338
  function wplc_choose_final_loggedin_control($logged_in,$logged_in_via_app) {
2339
+ return wplc_get_online_agent_users_count()>0;
2340
+ }
2341
+
2342
+ function wplc_return_online_agents_array() {
2343
+ $result = array(
2344
+ 'result' => true,
2345
+ 'agents' => wplc_get_online_agents_list()
2346
+ );
2347
+ return json_encode($result);
 
 
 
 
 
 
 
 
 
 
 
 
 
2348
  }
2349
 
2350
  /**
2351
  * Latch onto the original callback for this plugin's ajax requests
2352
  * @return void
2353
  */
2354
+ function wplc_choose_hook_control_action_callback() {
2355
+ if ($_POST['action'] == 'wplc_choose_accepting') {
2356
+ $user_id = get_current_user_id();
2357
+ wplc_set_agent_accepting($user_id, true);
2358
+ do_action("wplc_hook_set_transient");
2359
+ echo wplc_return_online_agents_array();
2360
+ return;
2361
+ }
2362
 
2363
+ if ($_POST['action'] == 'wplc_choose_not_accepting') {
2364
+ $user_id = get_current_user_id();
2365
+ wplc_set_agent_accepting($user_id, false);
2366
+ delete_user_meta($user_id, "wplc_chat_agent_online");
2367
+ delete_transient('wplc_is_admin_logged_in');
2368
+ echo wplc_return_online_agents_array();
2369
+ return;
2370
+ }
2371
 
2372
+ if ($_POST['action'] == 'wplc_agent_list') {
2373
+ echo wplc_return_online_agents_array();
2374
+ return;
2375
+ }
 
 
 
2376
 
2377
+ if ($_POST['action'] == "wplc_typing") {
2378
+ if (isset($_POST['cid']) && isset($_POST['user']) && isset($_POST['type'])) {
2379
+ if ((!wplc_user_is_agent() && wplc_check_user_request($_POST['cid'])) || wplc_user_is_agent()) {
2380
+ echo wplc_typing_mrg(sanitize_text_field($_POST['user']), intval($_POST['cid']), sanitize_text_field($_POST['type']));
 
2381
  }
2382
  }
2383
+ return;
2384
+ }
2385
 
2386
+ if ($_POST['action'] == 'wplc_upload_file') {
2387
+ $upload_dir = wp_upload_dir();
2388
+ $user_dirname = $upload_dir['basedir'];
2389
+ $cid=0;
2390
+ $u_id_check=0;
2391
+ if (isset($_POST['cid'])) {
2392
+ if (!wplc_user_is_agent()) {
2393
+ if (wplc_check_user_request($_POST['cid'])) {
2394
+ $u_id_check = 1;
2395
+ }
2396
+ } else {
2397
+ $u_id_check = 1;
2398
+ }
2399
+ if ($u_id_check === 1) {
2400
+ $cid = sanitize_text_field($_POST['cid']);
2401
+ if (!filter_var($cid, FILTER_VALIDATE_INT)) {
2402
+ /* We need to identify if this CID is a node CID, and if so, return the WP CID */
2403
+ $cid = wplc_return_chat_id_by_rel($cid);
2404
+ }
2405
+ $cid = intval($cid);
2406
+ if (!file_exists( $user_dirname."/wp_live_chat/")) {
2407
+ @mkdir($user_dirname.'/wp_live_chat/');
2408
+ }
2409
+ if (!realpath($user_dirname."/wp_live_chat/" . $cid)) {
2410
+ @mkdir( $user_dirname.'/wp_live_chat/'. $cid );
2411
+ }
2412
+ if (isset($_FILES['file']) && isset($_POST['timestamp'])) {
2413
+ $file_name = strtolower( sanitize_file_name($_FILES['file']['name']) );
2414
+ $file_name = basename($file_name); //This prevents traversal
2415
+ if (wplc_check_file_name_for_safe_extension($file_name) && wplc_check_file_mime_type($_FILES['file']['tmp_name'])) {
2416
+ $upload_file_name = $file_name;
2417
+ while (file_exists($user_dirname . "/wp_live_chat/" . $cid . "/" . $upload_file_name)) {
2418
+ $upload_file_name = substr($file_name,0,strrpos($file_name, '.')).mt_rand(1000,9999).substr($file_name,strrpos($file_name, '.'));
2419
+ }
2420
+ if (move_uploaded_file($_FILES['file']['tmp_name'], $user_dirname."/wp_live_chat/" . $cid . "/" . $upload_file_name)) {
2421
+ //File has been uploaded, let's now go ahead and check the mime type
2422
+ $response = $upload_dir['baseurl']."/wp_live_chat/" . $cid . "/" . $upload_file_name;
2423
+ echo $response;
2424
+ } else {
2425
+ echo "ERROR: Upload failed";
2426
+ }
2427
+ } else {
2428
+ echo "ERROR: Security Violation";
2429
+ }
2430
+ }
2431
+ } else {
2432
+ echo "ERROR: Chat ID Tampering Detected.";
2433
+ }
2434
+ } else {
2435
+ echo "ERROR: Upload failed. Invalid Chat ID.";
 
 
 
 
 
 
 
 
 
2436
  }
2437
+ wp_die();
2438
+ }
2439
  }
2440
 
2441
  function wplc_typing_mrg($user,$cid,$type) {
2487
  'accepting_status' => __('Status (Online)', 'wp-live-chat-support'),
2488
  'accepting_chats' => __('Online', 'wp-live-chat-support'),
2489
  'not_accepting_chats' => __('Offline', 'wp-live-chat-support'),
2490
+ 'not_accepting_status' => __('Status (Offline)', 'wp-live-chat-support'),
2491
+ 'agent_online_singular' => __('Chat Agent Online', 'wp-live-chat-support'),
2492
+ 'agent_online_plural' => __('Chat Agents Online', 'wp-live-chat-support')
2493
  );
2494
+
2495
  wp_localize_script('wplc-choose-script', 'wplc_choose_admin_strings', $wpc_admin_js_strings);
2496
+ wplc_register_common_node();
2497
 
2498
  $wplc_current_user_id = get_current_user_id();
2499
 
2500
+ if (wplc_get_agent_accepting($wplc_current_user_id)) {
2501
  /* user is online */
2502
  wp_localize_script('wplc-choose-script', 'wplc_choose_accept_chats', array('value'=>true));
2503
  } else {
2731
  * @return void
2732
  *
2733
  */
2734
+ add_filter("wplc_filter_admin_javascript","wplc_ic_filter_control_admin_javascript");
2735
+ function wplc_ic_filter_control_admin_javascript($data_array) {
2736
+ if (wplc_user_is_agent()) {
2737
+ $data_array['agent_id'] = get_current_user_id();
2738
+ }
2739
+ return $data_array;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2740
  }
2741
 
2742
  /**
2863
  */
2864
  if (!function_exists("wplc_ma_hook_control_admin_meny_layout_display_top")) {
2865
  function wplc_ma_hook_control_admin_meny_layout_display_top() {
2866
+ if (!wplc_user_is_agent()) {
2867
+ $warning = "<p style='color: red;'><b>".__('You are not a chat agent. Please make yourself a chat agent before trying to chat to visitors', 'wp-live-chat-support-multiple-agents')."</b></p>";
2868
+ echo $warning;
2869
+ }
2870
+ return;
 
 
2871
  }
2872
  }
2873
 
 
 
 
 
2874
  /**
2875
  * Assign the chat to the agent
2876
  *
2898
  }
2899
  }
2900
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2901
  /**
2902
  * Check if the chat has been answered by another chat agent
2903
  * @since 1.0.0
2973
  $admins->add_cap('wplc_ma_agent');
2974
  $uid = get_current_user_id();
2975
  update_user_meta($uid, 'wplc_ma_agent', 1);
2976
+ wplc_update_agent_time($uid);
2977
  }
2978
  }
2979
 
3001
 
3002
  if ($_POST['wplc_ma_agent'] == '1') {
3003
  $wplc_ma_user = new WP_User( $user_id );
3004
+ $wplc_ma_user->add_cap( 'wplc_ma_agent' );
3005
+ wplc_update_agent_time($user_id);
3006
  } else {
3007
  $wplc_ma_user = new WP_User( $user_id );
3008
  $wplc_ma_user->remove_cap( 'wplc_ma_agent' );
3283
  }
3284
  }
3285
 
 
3286
  if (!function_exists("wplc_filter_control_aid_in_action")) {
3287
+ add_filter("wplc_filter_aid_in_action","wplc_filter_control_aid_in_action");
3288
+ function wplc_filter_control_aid_in_action() {
3289
+ $aid = "";
3290
+ if (wplc_user_is_agent()) {
3291
+ $aid = "&aid=".get_current_user_id();
3292
+ }
3293
+ return $aid;
3294
+ }
 
3295
  }
3296
 
 
3297
  /**
3298
  *
3299
  *
3305
  if (!function_exists("wplc_ma_filter_control_admin_javascript")) {
3306
  add_filter("wplc_filter_admin_javascript","wplc_ma_filter_control_admin_javascript");
3307
  function wplc_ma_filter_control_admin_javascript($data_array) {
3308
+ if (wplc_user_is_agent()) {
3309
+ $data_array['agent_id'] = get_current_user_id();
3310
+ }
3311
+ return $data_array;
 
 
3312
  }
3313
  }
3314
 
 
 
 
 
3315
  /**
3316
  * Control the content below the visitor count
3317
  * @return void
3319
  if (!function_exists("wplc_ma_filter_control_chat_dashboard_visitors_online_bottom")) {
3320
  add_action("wplc_filter_chat_dahsboard_visitors_online_bottom","wplc_ma_filter_control_chat_dashboard_visitors_online_bottom",11);
3321
  function wplc_ma_filter_control_chat_dashboard_visitors_online_bottom($text) {
3322
+ $text = " <span class='wplc_agents_online'>".wplc_get_online_agent_users_count()."</span> ";
3323
  $text .= __("Agent(s) online",'wp-live-chat-support');
3324
  return $text;
3325
  }
3326
  }
3327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3328
  add_action('admin_bar_menu', 'wplc_maa_online_agents', 100);
3329
  function wplc_maa_online_agents() {
3330
  if (!current_user_can('wplc_ma_agent', array(null))) {
3345
  .wplc_green_circle{
3346
  background:rgb(103, 213, 82);
3347
  }
3348
+ .wplc_online_topbar_switch:before {
3349
+ color: #000 !important;
3350
+ }
3351
+
3352
+ .wplc_online_topbar_switch {
3353
+ width: 9px !important;
3354
+ height: 14px !important;
3355
+ margin-top: -1px !important;
3356
+ border: 1px solid #dedede !important;
3357
+ }
3358
+ .wplc_online_topbar_switch_online {
3359
+ background-color: rgb(96, 202, 76) !important;
3360
+ }
3361
+ .wplc_online_topbar_switch_offline {
3362
+ background-color: #de1b1b !important;
3363
+ }
3364
+
3365
  </style>
3366
  <?php
3367
+ $user_array = wplc_get_online_agent_users();
3368
+ $agent_count = count($user_array);
3369
  if ($agent_count>0) {
3370
  $circle_class = "wplc_green_circle";
3371
  if ($agent_count==1) {
3381
  global $wp_admin_bar;
3382
  $wp_admin_bar->add_menu( array(
3383
  'id' => 'wplc_ma_online_agents',
3384
+ 'title' => '<span class="wplc_circle '.$circle_class.'" id="wplc_ma_online_agents_circle"></span><span id="wplc_ma_online_agents_count">'.$agent_count.'</span> <span id="wplc_ma_online_agents_label">'.$chat_agents.'</span>',
3385
  'href' => false
3386
  ));
3387
 
3388
+ foreach($user_array as $user) {
3389
+ $wp_admin_bar->add_menu(array(
3390
+ 'id' => 'wplc_user_online_'.$user->ID,
3391
+ 'parent' => 'wplc_ma_online_agents',
3392
+ 'title' => $user->display_name,
3393
+ 'href' => false,
3394
+ ));
3395
+ }
3396
+
3397
+ if (is_admin()) {
3398
+ $wp_admin_bar->add_node( array(
3399
+ 'id' => 'wplc_ma_online_switch',
3400
+ 'meta' => array('class' => 'wplc_online_switch_'.(wplc_get_agent_accepting() ? 'online' : 'offline')),
3401
+ 'title' => '<input type="checkbox" id="wplc_online_topbar_switch" '.(wplc_get_agent_accepting() ? 'checked="checked"' : '').' class="wplc_online_topbar_switch wplc_online_topbar_switch_'.(wplc_get_agent_accepting() ? 'online' : 'offline').'" />
3402
+ <span id="wplc_ma_online_agent_text">'.(wplc_get_agent_accepting() ? __('Online', 'wp-live-chat-support') : __('Offline','wp-live-chat-support')).'
3403
+ </span>',
3404
+ 'href' => false
3405
+ ));
3406
  }
3407
  }
3408
 
3444
  if (!function_exists("wplc_maa_filter_control_check_if_logged_in")) {
3445
  add_filter("wplc_filter_is_admin_logged_in","wplc_maa_filter_control_check_if_logged_in",10,1);
3446
  function wplc_maa_filter_control_check_if_logged_in($logged_in) {
3447
+ $logged_in['site'] = wplc_one_agent_is_online();
3448
  return $logged_in;
3449
  }
3450
  }
3458
  if (!function_exists("wplc_maa_agent_logout")) {
3459
  add_action('wp_logout', 'wplc_maa_agent_logout');
3460
  function wplc_maa_agent_logout(){
3461
+ delete_user_meta(get_current_user_id(), "wplc_chat_agent_online");
 
3462
  }
3463
  }
3464
 
 
 
 
 
 
 
 
 
 
 
3465
  /**
3466
  * Add the JS file to the admin screen
3467
  * @return void
3488
  do_action("wplc_maa_hook_head");
3489
  }
3490
 
3491
+ if (!function_exists("wplc_ma_hook_control_action_callback")) { // TODO: unclear
3492
+ add_action("wplc_hook_set_transient","wplc_ma_hook_control_set_transient",9);
3493
+ function wplc_ma_hook_control_set_transient() {
3494
+ $should_set_transient = apply_filters("wplc_filter_control_set_transient",true);
3495
+ if ($should_set_transient) {
3496
+ if (isset($_POST['user_id'])) { $user_id = sanitize_text_field($_POST['user_id']); } else { $user_id = get_current_user_id(); }
3497
+ wplc_update_agent_time($user_id);
3498
+ }
3499
+ remove_action("wplc_hook_set_transient","wplc_hook_control_set_transient");
3500
+ }
 
3501
  }
3502
 
 
3503
  if (!function_exists("wplc_ma_hook_control_remove_transient")) {
3504
  add_action("wplc_hook_remove_transient","wplc_ma_hook_control_remove_transient",9);
3505
  function wplc_ma_hook_control_remove_transient() {
3513
  * @return void
3514
  * @since 1.0.00
3515
  */
3516
+ add_action("wplc_hook_action_callback","wplc_ma_hook_control_action_callback");
3517
+ function wplc_ma_hook_control_action_callback() {
3518
+
3519
+ if ($_POST['action'] == "wplc_add_agent") {
3520
+ if (current_user_can("manage_options")) {
3521
+ $uid = sanitize_text_field(intval($_POST['uid']));
3522
+ if (isset($uid)) {
3523
+ update_user_meta($uid, 'wplc_ma_agent', true);
3524
+ echo "1";
3525
+ } else {
3526
+ echo "0";
3527
+ }
3528
+ }
3529
+ }
3530
+
3531
+ if ($_POST['action'] == "wplc_remove_agent") {
3532
+ if (current_user_can("manage_options")) {
3533
+ $uid = sanitize_text_field(intval($_POST['uid']));
3534
+ if (isset($uid)) {
3535
+ delete_user_meta($uid, 'wplc_ma_agent');
3536
+ echo "1";
3537
+ } else {
3538
+ echo "0";
3539
+ }
3540
+ }
3541
+ }
 
 
 
 
 
 
 
 
3542
 
3543
+ if ($_POST['action'] == "wplc_macro") {
3544
+ if (wplc_user_is_agent()) {
3545
+ if (isset($_POST['postid'])) {
3546
+ $post_id = sanitize_text_field($_POST['postid']);
3547
+ } else {
3548
+ return false;
3549
+ }
3550
+ if ($post_id > 0) {
3551
+ $post_details = get_post($post_id);
3552
+ if ($post_details) {
3553
+ echo json_encode(nl2br($post_details->post_content));
3554
+ } else {
3555
+ echo json_encode("No post with that ID");
3556
+ die();
 
 
3557
  }
3558
+ } else {
3559
+ echo json_encode("No macro with that ID");
3560
+ die();
3561
+ }
3562
+ } else {
3563
+ echo json_encode("You do not have permission to perform this action.");
3564
+ die();
3565
+ }
3566
+ }
3567
 
3568
+ if ($_POST['action'] == 'wplc_record_chat_rating' ) {
3569
+ $rating_id = sanitize_text_field($_POST['cid']);
3570
+ $rating_score = sanitize_text_field($_POST['rating']);
3571
+ $u_id_check=0;
3572
+ if (wplc_check_user_request($_POST['cid'])) {
3573
+ $u_id_check = 1;
3574
+ }
3575
+ if ($u_id_check === 1) {
3576
+ if (!filter_var($rating_id, FILTER_VALIDATE_INT)) {
3577
+ /* We need to identify if this CID is a node CID, and if so, return the WP CID */
3578
+ $rating_id = wplc_return_chat_id_by_rel($rating_id);
3579
+ }
3580
+ $nifty_record_rating = nifty_record_rating_mrg($rating_id, $rating_score);
3581
+ if ($nifty_record_rating) {
3582
+ echo 'rating added';
3583
+ } else {
3584
+ echo "There was an error sending your chat message. Please contact support";
3585
+ }
3586
+ wp_die();
3587
+ } else {
3588
+ echo "There was an error sending your chat rating. Please contact support";
3589
+ wp_die();
3590
+ }
3591
+ }
 
 
 
 
 
 
 
 
3592
  }
3593
 
3594
  /**
3596
  * @return void
3597
  * @since 1.0.00
3598
  */
3599
+ function wplc_maa_set_agents_online($user_id) {
3600
+ if (wplc_user_is_agent($user_id)) {
3601
+ wplc_update_agent_time($user_id);
3602
+ }
3603
+ wplc_check_agents_timeout();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3604
  }
3605
 
 
3606
  /* WPLC Social Icons Filter*/
3607
  // add_filter("wplc_filter_chat_header_above","wplc_chat_social_div_mrg",5,2);
3608
  // add_filter("wplc_filter_chat_4th_layer_below_input","wplc_chat_social_div_mrg",5,2);
3830
 
3831
 
3832
  add_filter('wplc_reporting_tab_content', 'wplc_reporting_tab_content_filter_experience_ratings_control_mrg', 10, 1);
3833
+ function wplc_reporting_tab_content_filter_experience_ratings_control_mrg($tabs_array) {
3834
+ $ratings = "<h3>".__("Agent Statistics", 'wp-live-chat-support')."</h3>";
3835
+ $user_array = wplc_get_agent_users();
3836
+ $ratings .= "<style>";
3837
+ $ratings .= ".wplc_agent_grav_report { display:inline-block; }";
3838
+ $ratings .= ".wplc_agent_card_details { display:inline-block; margin-left: 5px;}";
3839
+ $ratings .= ".wplc_agent_card { width:100%; }";
3840
+ $ratings .= ".wplc_agent_container {
3841
+ width: 30%;
3842
+ padding: 5px;
3843
+ border-radius: 7px;
3844
+ box-shadow: 0px 0px 5px 2px #9999992b;
3845
+ display: inline-block;
3846
+ margin-right: 13px;
3847
+ vertical-align: top;
3848
+ margin-bottom:10px;
3849
+ }";
3850
+ $ratings .= ".wplc_agent_data {
3851
+ max-height: 200px;
3852
+ overflow-y: auto;
3853
+ padding: 5px;
3854
+ border: 1px lightgrey solid;
3855
+ }";
3856
+ $ratings .= "</style>";
3857
+
3858
+ foreach ($user_array as $user) {
3859
+ $ratings .= "<div class='wplc_agent_container'>";
3860
+ $rating_stats = nifty_get_rating_report_mrg($user->ID);
3861
+ $ratings .= "<div class='wplc_agent_card'>";
3862
+ $ratings .= "<img class='wplc_agent_grav_report' src=\"//www.gravatar.com/avatar/" . md5($user->user_email) . "?s=80&d=mm\" />";
3863
+ $ratings .= "<div class='wplc_agent_card_details'>";
3864
+ $ratings .= "<strong>" . $user->display_name . "</strong><br>";
3865
+ $ratings .= "<small>" . $user->user_email . "</small><br>";
3866
+ $ratings .= "<hr>";
3867
+ $ratings .= "<small><strong>".__("Satisfaction Rating", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "--" : $rating_stats['percentage'] ). "%</small><br>";
3868
+ $ratings .= "<small><strong>".__("Rating Count", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['total_ratings'])." (".__("Good",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['good_count']). " || ".__("Bad",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['bad_count']). ")</small>";
3869
+ $ratings .= "</div>";
3870
+ $ratings .= "</div>";
3871
+ $ratings .= "</div>";
3872
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3873
 
3874
+ $rating_stats = nifty_get_rating_report_mrg(0);
3875
+ if (!empty($rating_stats[0]) && $rating_stats[0] !== false) {
3876
+ $ratings .= "<div class='wplc_agent_container'>";
3877
+ $ratings .= "<div class='wplc_agent_card'>";
3878
+ $ratings .= "<div class='wplc_agent_card_details'>";
3879
+ $ratings .= "<strong>No Agent</strong><br>";
3880
+ $ratings .= "<small>Reviewed before agent joined, or with multiple agents</small><br>";
3881
+ $ratings .= "<hr>";
3882
+ $ratings .= "<small><strong>".__("Satisfaction Rating", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "--" : $rating_stats['percentage'] ). "%</small><br>";
3883
+ $ratings .= "<small><strong>".__("Rating Count", 'wp-live-chat-support').":</strong> " . (is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['total_ratings'])." (".__("Good",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['good_count']). " || ".__("Bad",'wp-live-chat-support').": ".(is_bool($rating_stats) && $rating_stats == false ? "0" : $rating_stats['bad_count']). ")</small>";
3884
+ $ratings .= "</div>";
3885
+ $ratings .= "</div>";
3886
+ $ratings .= "</div>";
3887
+ }
3888
 
3889
+ $tabs_array['ux_ratings'] = $ratings;
3890
+ return $tabs_array;
3891
  }
3892
 
3893
  add_action('admin_enqueue_scripts', 'wplc_reporting_scripts_mrg');
4520
  function wplc_register_common_node() {
4521
  global $wplc_allowed_extensions;
4522
  $wplc_settings = wplc_get_options();
4523
+ wp_register_script('wplc-admin-js-agent-common', WPLC_PLUGIN_URL.'js/wplc_common_node.js', null, WPLC_PLUGIN_VERSION, false);
4524
  $current_user=wp_get_current_user();
4525
  $date_days=array();
4526
  for($i=0;$i<7;$i++) {
4929
  return $wplc_settings;
4930
  }
4931
 
4932
+ function wplc_ajax_generate_new_tokens() {
4933
+ if (isset($_POST['action']) && ($_POST['action'] === "wplc_generate_new_node_token" || $_POST['action'] === "wplc_new_secret_key") && isset($_POST['nonce']) && wplc_user_is_agent()) {
4934
+ $nonce = $_POST['nonce'];
4935
+ $action = $_POST['action'];
4936
+ $error = false;
4937
+ switch($action) {
4938
+ case 'wplc_generate_new_node_token':
4939
+ if (wp_verify_nonce( $nonce, 'generate_new_token')) {
4940
+ $res = wplc_node_server_token_get(true);
4941
+ echo $res;
4942
+ } else {
4943
+ $error = true;
4944
+ }
4945
+ break;
4946
+
4947
+ case 'wplc_new_secret_key':
4948
+ if (wp_verify_nonce( $nonce, 'generate_new_secret_token')) {
4949
+ $user_token = wplc_api_s_key_create();
4950
+ update_option("wplc_api_secret_token", $user_token);
4951
+ echo $user_token;
4952
+ } else {
4953
+ $error = true;
4954
+ }
4955
+ break;
4956
+ }
4957
+ if ($error) {
4958
+ _e("You do not have permission to perform this action",'wp-live-chat-support');
4959
+ }
4960
+ } else {
4961
+ _e("You do not have permission to perform this action",'wp-live-chat-support');
4962
+ }
4963
+ wp_die();
4964
+ }
4965
+
4966
+ // **********************************
4967
+ // Agents functions
4968
+ // **********************************
4969
+
4970
+ /**
4971
+ * Checks if specified user is an agent. Default is get_current_user_id
4972
+ * @return bool
4973
+ */
4974
+ function wplc_user_is_agent($uid=0) {
4975
+ if (empty($uid)) {
4976
+ $uid=get_current_user_id();
4977
+ }
4978
+ return !empty(get_user_meta(intval($uid), 'wplc_ma_agent', true));
4979
+ }
4980
+
4981
+ /**
4982
+ * Returns a list of users with agent attribute
4983
+ * @return array(WPuser)
4984
+ */
4985
+ function wplc_get_agent_users() {
4986
+ return get_users(array('meta_key' => 'wplc_ma_agent'));
4987
+ }
4988
+
4989
+ /**
4990
+ * Returns a list of online agents
4991
+ * @return array(WPuser)
4992
+ */
4993
+ function wplc_get_online_agent_users() {
4994
+ $agents = wplc_internal_get_all_agents_users_online();
4995
+ $online_agents = array();
4996
+ foreach($agents as $v) {
4997
+ if (wplc_get_agent_accepting($v->ID)) {
4998
+ $online_agents[]=$v;
4999
+ }
5000
+ }
5001
+ return $online_agents;
5002
+ }
5003
+
5004
+ function wplc_update_agent_time($uid=0) {
5005
+ if (empty($uid)) {
5006
+ $uid=get_current_user_id();
5007
+ }
5008
+ update_user_meta($uid, "wplc_chat_agent_online", time());
5009
+ }
5010
+
5011
+ /**
5012
+ * Checks if a specified agent is online. Default is get_current_user_id
5013
+ * @return bool
5014
+ */
5015
+ function wplc_agent_is_online($uid) {
5016
+ $agents = wplc_get_online_agent_users();
5017
+ foreach($agents as $agent) {
5018
+ if ($agent->ID == $uid) {
5019
+ return true;
5020
+ }
5021
+ }
5022
+ return false;
5023
+ }
5024
+
5025
+ // return number of online agents
5026
+ function wplc_get_online_agent_users_count() {
5027
+ return count(wplc_get_online_agent_users());
5028
+ }
5029
+
5030
+ /**
5031
+ * Checks if there at least one agent online
5032
+ * @return bool
5033
+ */
5034
+ function wplc_one_agent_is_online() {
5035
+ return wplc_get_online_agent_users_count()>0;
5036
+ }
5037
+
5038
+ // check if agents are really online by checking heartbeat on wplc_chat_agent_online meta
5039
+ function wplc_check_agents_timeout() {
5040
+ $agents = wplc_get_agent_users();
5041
+ foreach ($agents as $user) {
5042
+ $check = get_user_meta($user->ID, "wplc_chat_agent_online");
5043
+ if (isset($check[0])) {
5044
+ $last_logged_in_time = $check[0];
5045
+ if ($last_logged_in_time > 0) {
5046
+ if ((time() - $last_logged_in_time) < 120) {
5047
+ /* do nothing, they are online */
5048
+ } else {
5049
+ /* this user has not sent a heartbeat in over 120 seconds */
5050
+ delete_user_meta($user->ID, "wplc_chat_agent_online");
5051
+ }
5052
+ }
5053
+ }
5054
+ }
5055
+ }
5056
+
5057
+ function wplc_get_online_agents_list() {
5058
+ $agents = wplc_internal_get_all_agents_users_online();
5059
+ $accepting = wplc_internal_get_all_agents_accepting();
5060
+ $result = array();
5061
+ foreach($agents as $agent) {
5062
+ if (!empty($accepting[$agent->ID])) {
5063
+ $result[]=array('name'=> $agent->display_name);
5064
+ }
5065
+ }
5066
+ return $result;
5067
+ }
5068
+
5069
+ function wplc_get_agent_accepting($uid=0) {
5070
+ if (empty($uid)) {
5071
+ $uid=get_current_user_id();
5072
+ }
5073
  $wplc_settings = wplc_get_options();
5074
+ $choose_array = wplc_internal_get_all_agents_accepting();
5075
  if (!isset($choose_array[$uid])) {
5076
  $choose_array[$uid]=true;
5077
  update_option("WPLC_CHOOSE_ACCEPTING", $choose_array);
5083
  return $choose_array[$uid];
5084
  }
5085
 
5086
+ function wplc_set_agent_accepting($uid, $online) {
5087
+ $choose_array = wplc_internal_get_all_agents_accepting();
5088
  if (!isset($choose_array[$uid]) || $choose_array[$uid]!=boolval($online)) {
5089
  $choose_array[$uid]=boolval($online);
5090
  update_option("WPLC_CHOOSE_ACCEPTING", $choose_array);
5091
  }
5092
  }
5093
 
5094
+ function wplc_internal_get_all_agents_accepting() {
5095
  $choose_array = get_option("WPLC_CHOOSE_ACCEPTING");
5096
  if (!is_array($choose_array)) {
5097
  $choose_array = array();
5099
  return $choose_array;
5100
  }
5101
 
5102
+ function wplc_internal_get_all_agents_users_online() {
5103
+ $agents = get_users(array('meta_key'=> 'wplc_chat_agent_online'));
5104
+ if (!is_array($agents)) {
5105
+ $agents = array();
5106
+ }
5107
+ return $agents;
5108
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/dashboard_page.php CHANGED
@@ -46,7 +46,7 @@ if ( ! defined( 'ABSPATH' ) ) {
46
  <div class="wplc_panel_heading"><i class="fa fa-tasks" aria-hidden="true"></i> <?php _e("Dashboard",'wp-live-chat-support'); ?></div>
47
  <div class="wplc_material_panel">
48
  <div class="wplc_dashboard_activity">
49
- <h3><?php printf( __( 'Hi %s! Current activity: %s Active Visitor(s) and %s Active Agent(s).', 'wp-live-chat-support'), $user->display_name, '<span id=\'totalVisitors\' class="wplc_dashboard_activity_numbers">...</span>', '<span class="wplc_dashboard_activity_numbers">'.wplc_maa_total_agents_online().'</span>'); ?></h3>
50
  </div>
51
  <div class="wplc_panel_col wplc_dashboard_buttons_outer">
52
  <div class="wplc_dashboard_button_item">
46
  <div class="wplc_panel_heading"><i class="fa fa-tasks" aria-hidden="true"></i> <?php _e("Dashboard",'wp-live-chat-support'); ?></div>
47
  <div class="wplc_material_panel">
48
  <div class="wplc_dashboard_activity">
49
+ <h3><?php printf( __( 'Hi %s! Current activity: %s Active Visitor(s) and %s Active Agent(s).', 'wp-live-chat-support'), $user->display_name, '<span id=\'totalVisitors\' class="wplc_dashboard_activity_numbers">...</span>', '<span class="wplc_dashboard_activity_numbers">'.wplc_get_online_agent_users_count().'</span>'); ?></h3>
50
  </div>
51
  <div class="wplc_panel_col wplc_dashboard_buttons_outer">
52
  <div class="wplc_dashboard_button_item">
includes/settings_page.php CHANGED
@@ -185,14 +185,6 @@ $wplc_settings = wplc_get_options();
185
  <textarea cols="45" rows="5" name="wplc_user_alternative_text" ><?php echo esc_textarea($wplc_settings['wplc_user_alternative_text']); ?></textarea>
186
  </td>
187
  </tr>
188
- <tr>
189
- <td width='300' valign='top'>
190
- <?php _e("Use Logged In User Details",'wp-live-chat-support')?>: <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("A user's Name and Email Address will be used by default if they are logged in.", 'wp-live-chat-support') ?>"></i>
191
- </td>
192
- <td valign='top'>
193
- <input type="checkbox" value="1" name="wplc_loggedin_user_info"<?php echo ($wplc_settings['wplc_loggedin_user_info'] ? ' checked' : '');?> />
194
- </td>
195
- </tr>
196
  <tr>
197
  <td width='200' valign='top'>
198
  <?php _e("Enable On Mobile Devices","wplivechat"); ?>: <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("Disabling this will mean that the Chat Box will not be displayed on mobile devices. (Smartphones and Tablets)", "wplivechat") ?>"></i>
@@ -414,6 +406,21 @@ $wplc_settings = wplc_get_options();
414
  </select>
415
  </td>
416
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  <tr>
418
  <td width='300'>
419
  <?php _e("Automatic Chatbox Pop-Up",'wp-live-chat-support') ?> <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("Expand the chat box automatically (prompts the user to enter their name and email address).",'wp-live-chat-support') ?>"></i>
@@ -454,6 +461,14 @@ $wplc_settings = wplc_get_options();
454
  <input type="checkbox" name="wplc_display_to_loggedin_only" value="1"<?php echo ($wplc_settings['wplc_display_to_loggedin_only'] ? ' checked' : ''); ?>/>
455
  </td>
456
  </tr>
 
 
 
 
 
 
 
 
457
  <tr>
458
  <td>
459
  <?php _e("Display a timestamp in the chat window:", 'wp-live-chat-support') ?>
@@ -484,7 +499,7 @@ $wplc_settings = wplc_get_options();
484
  </td>
485
  <td>
486
  <input type="checkbox" name="wplc_disable_emojis"<?php if ($wplc_settings['wplc_disable_emojis']) {echo ' checked="checked"';} ?>/>
487
- </tr>
488
  <?php
489
  }
490
  ?>
@@ -583,7 +598,6 @@ $wplc_settings = wplc_get_options();
583
  <input id="wplc_btn_upload_icon" name="wplc_btn_upload_icon" type="button" value="<?php _e("Upload Icon", 'wp-live-chat-support') ?>" />
584
  <input id="wplc_btn_select_default_icon" name="wplc_btn_select_default_icon" type="button" value="<?php _e("Select Default Icon", 'wp-live-chat-support') ?>" />
585
  <br/>
586
- <input id="wplc_btn_remove_icon" name="wplc_btn_remove_icon" type="button" value="<?php _e("Remove Icon", 'wp-live-chat-support') ?>" />
587
  <?php _e("Recommended Size 50px x 50px", 'wp-live-chat-support') ?>
588
 
589
  <div id="wplc_default_chat_icons" style="display: none">
@@ -630,14 +644,16 @@ $wplc_settings = wplc_get_options();
630
  <?php _e("Picture", 'wp-live-chat-support') ?>:
631
  </td>
632
  <td>
633
- <div style="display:block" id="wplc_pic_area">
634
  <img src="<?php echo urldecode($wplc_settings['wplc_chat_pic']); ?>" width="60px"/>
635
  </div>
636
  <input id="wplc_upload_pic" name="wplc_upload_pic" type="hidden" size="35" class="regular-text" maxlength="700" value=""/>
637
  <br/>
638
- <input id="wplc_btn_upload_pic" name="wplc_btn_upload_pic" type="button" value="<?php _e("Upload Image", 'wp-live-chat-support') ?>" />
 
 
639
  <br/>
640
- <input id="wplc_btn_remove_pic" name="wplc_btn_remove_pic" type="button" value="<?php _e("Remove Image", 'wp-live-chat-support') ?>" />
641
  <?php _e("Recommended Size 60px x 60px", 'wp-live-chat-support') ?>
642
  </td>
643
  </tr>
@@ -655,7 +671,7 @@ $wplc_settings = wplc_get_options();
655
  <br/>
656
  <input id="wplc_btn_upload_logo" name="wplc_btn_upload_logo" type="button" value="<?php _e("Upload Logo", 'wp-live-chat-support') ?>" />
657
  <br/>
658
- <input id="wplc_btn_remove_logo" name="wplc_btn_remove_logo" type="button" value="<?php _e("Remove Logo", 'wp-live-chat-support') ?>" />
659
  <?php _e("Recommended Size 250px x 40px", 'wp-live-chat-support') ?>
660
  </td>
661
  </tr>
@@ -1152,37 +1168,31 @@ $wplc_settings = wplc_get_options();
1152
 
1153
 
1154
  <?php
1155
-
1156
- $user_array = get_users(array(
1157
- 'meta_key' => 'wplc_ma_agent',
1158
- ));
1159
 
1160
  echo "<h3>".__('Chat Agents', 'wp-live-chat-support')."</h3>";
1161
 
1162
  $wplc_agents = "<div class='wplc_agent_container'><ul>";
1163
 
1164
- if ($user_array) {
1165
- foreach ($user_array as $user) {
1166
 
1167
- $wplc_agents .= "<li id=\"wplc_agent_li_".$user->ID."\">";
1168
- $wplc_agents .= "<p><img src=\"//www.gravatar.com/avatar/" . md5($user->user_email) . "?s=60&d=mm\" /></p>";
1169
- $check = get_user_meta($user->ID,"wplc_chat_agent_online");
1170
- if ($check) {
1171
- $wplc_agents .= "<span class='wplc_status_box wplc_type_returning'>".__("Logged In",'wp-live-chat-support')."</span>";
1172
- }
1173
- $wplc_agents .= "<h3>" . esc_html($user->display_name) . "</h3>";
1174
-
1175
- $wplc_agents .= "<small>" . esc_html($user->user_email) . "</small>";
1176
 
1177
- $wplc_agents .= apply_filters("wplc_pro_agent_list_before_button_filter", "", $user);
1178
 
1179
- if (get_current_user_id() == $user->ID) {
1180
- } else {
1181
- $wplc_agents .= "<p><button class='button button-secondary wplc_remove_agent' id='wplc_remove_agent_".$user->ID."' uid='".$user->ID."'>".__("Remove",'wp-live-chat-support')."</button></p>";
1182
- }
1183
- $wplc_agents .= "</li>";
1184
- }
1185
- }
1186
  echo $wplc_agents;
1187
  ?>
1188
  <li style='width:150px;' id='wplc_add_new_agent_box'>
@@ -1194,20 +1204,17 @@ $wplc_settings = wplc_get_options();
1194
  $blogusers = get_users( array( 'role' => 'administrator', 'fields' => array( 'display_name','ID','user_email' ) ) );
1195
  // Array of stdClass objects.
1196
  foreach ( $blogusers as $user ) {
1197
- $is_agent = get_user_meta(intval( $user->ID ), 'wplc_ma_agent', true);
1198
- if(!$is_agent){ echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Administrator','wp-live-chat-support').')</option>'; }
1199
  }
1200
  $blogusers = get_users( array( 'role' => 'editor', 'fields' => array( 'display_name','ID','user_email' ) ) );
1201
  // Array of stdClass objects.
1202
  foreach ( $blogusers as $user ) {
1203
- $is_agent = get_user_meta(intval( $user->ID ), 'wplc_ma_agent', true);
1204
- if(!$is_agent){ echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Editor','wp-live-chat-support').')</option>'; }
1205
  }
1206
  $blogusers = get_users( array( 'role' => 'author', 'fields' => array( 'display_name','ID','user_email' ) ) );
1207
  // Array of stdClass objects.
1208
  foreach ( $blogusers as $user ) {
1209
- $is_agent = get_user_meta(intval( $user->ID ), 'wplc_ma_agent', true);
1210
- if(!$is_agent){ echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Author','wp-live-chat-support').')</option>'; }
1211
  }
1212
  ?>
1213
  </select>
185
  <textarea cols="45" rows="5" name="wplc_user_alternative_text" ><?php echo esc_textarea($wplc_settings['wplc_user_alternative_text']); ?></textarea>
186
  </td>
187
  </tr>
 
 
 
 
 
 
 
 
188
  <tr>
189
  <td width='200' valign='top'>
190
  <?php _e("Enable On Mobile Devices","wplivechat"); ?>: <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("Disabling this will mean that the Chat Box will not be displayed on mobile devices. (Smartphones and Tablets)", "wplivechat") ?>"></i>
406
  </select>
407
  </td>
408
  </tr>
409
+ <tr>
410
+ <td>
411
+ <?php
412
+ _e('Chat box height (percent of the page)', 'wp-live-chat-support');
413
+ ?>
414
+ </td>
415
+ <td>
416
+ <select id='wplc_chatbox_height' name='wplc_chatbox_height'>
417
+ <?php
418
+ for($i=30;$i<90;$i=$i+10) {
419
+ echo '<option value="'.$i.'" '.($wplc_settings['wplc_chatbox_height']==$i ? 'selected' : '').'>'.$i.'%</option>';
420
+ }
421
+ ?>
422
+ </select>
423
+ </tr>
424
  <tr>
425
  <td width='300'>
426
  <?php _e("Automatic Chatbox Pop-Up",'wp-live-chat-support') ?> <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("Expand the chat box automatically (prompts the user to enter their name and email address).",'wp-live-chat-support') ?>"></i>
461
  <input type="checkbox" name="wplc_display_to_loggedin_only" value="1"<?php echo ($wplc_settings['wplc_display_to_loggedin_only'] ? ' checked' : ''); ?>/>
462
  </td>
463
  </tr>
464
+ <tr>
465
+ <td width='300' valign='top'>
466
+ <?php _e("Use Logged In User Details",'wp-live-chat-support')?>: <i class="fa fa-question-circle wplc_light_grey wplc_settings_tooltip" title="<?php _e("A user's Name and Email Address will be used by default if they are logged in.", 'wp-live-chat-support') ?>"></i>
467
+ </td>
468
+ <td valign='top'>
469
+ <input type="checkbox" value="1" name="wplc_loggedin_user_info"<?php echo ($wplc_settings['wplc_loggedin_user_info'] ? ' checked' : '');?> />
470
+ </td>
471
+ </tr>
472
  <tr>
473
  <td>
474
  <?php _e("Display a timestamp in the chat window:", 'wp-live-chat-support') ?>
499
  </td>
500
  <td>
501
  <input type="checkbox" name="wplc_disable_emojis"<?php if ($wplc_settings['wplc_disable_emojis']) {echo ' checked="checked"';} ?>/>
502
+ </tr>
503
  <?php
504
  }
505
  ?>
598
  <input id="wplc_btn_upload_icon" name="wplc_btn_upload_icon" type="button" value="<?php _e("Upload Icon", 'wp-live-chat-support') ?>" />
599
  <input id="wplc_btn_select_default_icon" name="wplc_btn_select_default_icon" type="button" value="<?php _e("Select Default Icon", 'wp-live-chat-support') ?>" />
600
  <br/>
 
601
  <?php _e("Recommended Size 50px x 50px", 'wp-live-chat-support') ?>
602
 
603
  <div id="wplc_default_chat_icons" style="display: none">
644
  <?php _e("Picture", 'wp-live-chat-support') ?>:
645
  </td>
646
  <td>
647
+ <div style="display:block" id="wplc_pic_area" default="<?php echo $wplc_default_settings_array['wplc_chat_pic'];?>">
648
  <img src="<?php echo urldecode($wplc_settings['wplc_chat_pic']); ?>" width="60px"/>
649
  </div>
650
  <input id="wplc_upload_pic" name="wplc_upload_pic" type="hidden" size="35" class="regular-text" maxlength="700" value=""/>
651
  <br/>
652
+ <input id="wplc_btn_upload_pic" name="wplc_btn_upload_pic" type="button" value="<?php _e("Upload Image", 'wp-live-chat-support') ?>" />
653
+ <input id="wplc_btn_select_default_pic" name="wplc_btn_select_default_pic" type="button" value="<?php _e("Select Default Image", 'wp-live-chat-support') ?>" />
654
+
655
  <br/>
656
+ <input id="wplc_btn_remove_pic" name="wplc_btn_remove_pic" type="button" value="<?php _e("Remove Image", 'wp-live-chat-support') ?>" /><br/>
657
  <?php _e("Recommended Size 60px x 60px", 'wp-live-chat-support') ?>
658
  </td>
659
  </tr>
671
  <br/>
672
  <input id="wplc_btn_upload_logo" name="wplc_btn_upload_logo" type="button" value="<?php _e("Upload Logo", 'wp-live-chat-support') ?>" />
673
  <br/>
674
+ <input id="wplc_btn_remove_logo" name="wplc_btn_remove_logo" type="button" value="<?php _e("Remove Logo", 'wp-live-chat-support') ?>" /><br/>
675
  <?php _e("Recommended Size 250px x 40px", 'wp-live-chat-support') ?>
676
  </td>
677
  </tr>
1168
 
1169
 
1170
  <?php
1171
+ $user_array = wplc_get_agent_users();
 
 
 
1172
 
1173
  echo "<h3>".__('Chat Agents', 'wp-live-chat-support')."</h3>";
1174
 
1175
  $wplc_agents = "<div class='wplc_agent_container'><ul>";
1176
 
1177
+ foreach ($user_array as $user) {
 
1178
 
1179
+ $wplc_agents .= "<li id=\"wplc_agent_li_".$user->ID."\">";
1180
+ $wplc_agents .= "<p><img src=\"//www.gravatar.com/avatar/" . md5($user->user_email) . "?s=60&d=mm\" /></p>";
1181
+ if (wplc_agent_is_online($user->ID)) {
1182
+ $wplc_agents .= "<span class='wplc_status_box wplc_type_returning'>".__("Logged In",'wp-live-chat-support')."</span>";
1183
+ }
1184
+ $wplc_agents .= "<h3>" . esc_html($user->display_name) . "</h3>";
1185
+
1186
+ $wplc_agents .= "<small>" . esc_html($user->user_email) . "</small>";
 
1187
 
1188
+ $wplc_agents .= apply_filters("wplc_pro_agent_list_before_button_filter", "", $user);
1189
 
1190
+ if (get_current_user_id() == $user->ID) {
1191
+ } else {
1192
+ $wplc_agents .= "<p><button class='button button-secondary wplc_remove_agent' id='wplc_remove_agent_".$user->ID."' uid='".$user->ID."'>".__("Remove",'wp-live-chat-support')."</button></p>";
1193
+ }
1194
+ $wplc_agents .= "</li>";
1195
+ }
 
1196
  echo $wplc_agents;
1197
  ?>
1198
  <li style='width:150px;' id='wplc_add_new_agent_box'>
1204
  $blogusers = get_users( array( 'role' => 'administrator', 'fields' => array( 'display_name','ID','user_email' ) ) );
1205
  // Array of stdClass objects.
1206
  foreach ( $blogusers as $user ) {
1207
+ if (wplc_user_is_agent($user->ID)) {echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Administrator','wp-live-chat-support').')</option>'; }
 
1208
  }
1209
  $blogusers = get_users( array( 'role' => 'editor', 'fields' => array( 'display_name','ID','user_email' ) ) );
1210
  // Array of stdClass objects.
1211
  foreach ( $blogusers as $user ) {
1212
+ if (wplc_user_is_agent($user->ID)) { echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Editor','wp-live-chat-support').')</option>'; }
 
1213
  }
1214
  $blogusers = get_users( array( 'role' => 'author', 'fields' => array( 'display_name','ID','user_email' ) ) );
1215
  // Array of stdClass objects.
1216
  foreach ( $blogusers as $user ) {
1217
+ if (wplc_user_is_agent($user->ID)) { echo '<option id="wplc_selected_agent_'. intval( $user->ID ) .'" em="' . md5(sanitize_email( $user->user_email )) . '" uid="' . intval( $user->ID ) . '" em2="' . esc_attr( $user->user_email ) . '" name="' . esc_attr( $user->display_name ) . '" value="' . intval( $user->ID ) . '">' . esc_html( $user->display_name ) . ' ('.__('Author','wp-live-chat-support').')</option>'; }
 
1218
  }
1219
  ?>
1220
  </select>
includes/wplc_custom_fields.php CHANGED
@@ -506,52 +506,44 @@ function wplc_custom_field_rest_end_points_mrg(){
506
  }
507
 
508
  function wplc_custom_field_rest_get_info_mrg(WP_REST_Request $request){
509
-
510
- $return_array = array();
511
- if(isset($request)){
512
- if(isset($request['security'])){
513
- $check_token = get_option('wplc_api_secret_token');
514
- if($check_token !== false && $request['server_token'] === $check_token){
515
- if(isset($request['cid'])){
516
- if(wplc_ic_check_if_user_is_agent() !== "not_user_agent") {
517
- $cid = $request['cid'];
518
- if( ! filter_var($cid, FILTER_VALIDATE_INT) ) {
519
- $cid = wplc_return_chat_id_by_rel($cid);
520
- }
521
-
522
- $html = wplc_advanced_info_custom_fields_mrg("", $cid, "", false);
523
-
524
- $return_array['response'] = "Success";
525
- $return_array['code'] = "200";
526
- $return_array['data'] = $html;
527
- }else {
528
- $return_array['response'] = "You do not have permission to perform this action.";
529
- $return_array['code'] = "401";
530
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
531
- "cid" => "Chat ID");
532
- }
533
- } else {
534
- $return_array['response'] = "No 'cid' found";
535
- $return_array['code'] = "401";
536
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
537
- "cid" => "Chat ID");
538
- }
539
- } else {
540
- $return_array['response'] = "Nonce is invalid";
541
- $return_array['code'] = "401";
542
  }
543
- } else{
544
- $return_array['response'] = "No 'security' found";
 
 
 
 
545
  $return_array['code'] = "401";
546
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
547
- "cid" => "Chat ID");
 
 
 
 
548
  }
549
- }else{
550
- $return_array['response'] = "No request data found";
551
- $return_array['code'] = "400";
552
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
553
- "cid" => "Chat ID");
 
 
 
554
  }
555
-
556
- return $return_array;
 
 
 
 
557
  }
506
  }
507
 
508
  function wplc_custom_field_rest_get_info_mrg(WP_REST_Request $request){
509
+ $return_array = array();
510
+ if (isset($request)) {
511
+ if (isset($request['security'])) {
512
+ $check_token = get_option('wplc_api_secret_token');
513
+ if ($check_token !== false && $request['server_token'] === $check_token) {
514
+ if (isset($request['cid'])) {
515
+ if (wplc_user_is_agent()) {
516
+ $cid = $request['cid'];
517
+ if (!filter_var($cid, FILTER_VALIDATE_INT)) {
518
+ $cid = wplc_return_chat_id_by_rel($cid);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  }
520
+ $html = wplc_advanced_info_custom_fields_mrg("", $cid, "", false);
521
+ $return_array['response'] = "Success";
522
+ $return_array['code'] = "200";
523
+ $return_array['data'] = $html;
524
+ } else {
525
+ $return_array['response'] = "You do not have permission to perform this action.";
526
  $return_array['code'] = "401";
527
+ $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN", "cid" => "Chat ID");
528
+ }
529
+ } else {
530
+ $return_array['response'] = "No 'cid' found";
531
+ $return_array['code'] = "401";
532
+ $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN", "cid" => "Chat ID");
533
  }
534
+ } else {
535
+ $return_array['response'] = "Nonce is invalid";
536
+ $return_array['code'] = "401";
537
+ }
538
+ } else {
539
+ $return_array['response'] = "No 'security' found";
540
+ $return_array['code'] = "401";
541
+ $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN", "cid" => "Chat ID");
542
  }
543
+ } else {
544
+ $return_array['response'] = "No request data found";
545
+ $return_array['code'] = "400";
546
+ $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN", "cid" => "Chat ID");
547
+ }
548
+ return $return_array;
549
  }
includes/wplc_departments.php CHANGED
@@ -73,36 +73,35 @@ add_action("wplc_pro_custom_user_profile_field_after_content_hook", "wplc_mrg_de
73
  * @return void
74
  */
75
  function wplc_mrg_department_user_profile_departments($user){
76
- $user_is_agent = sanitize_text_field(get_the_author_meta( 'wplc_ma_agent', $user->ID));
77
- if($user_is_agent == "1"){
78
- $selected_department = intval(get_user_meta($user->ID, "wplc_user_department", true));
79
- if(current_user_can('manage_options', array(null))){
80
- ?>
81
- <table class="form-table">
82
- <tr>
83
- <th>
84
- <label for="wplc_user_department"><?php _e('Chat Department', 'wp-live-chat-support'); ?></label>
85
- </th>
86
- <td>
87
- <select id="wplc_user_department" name="wplc_user_department">
88
- <option value="-1"><?php _e("No Department", 'wp-live-chat-support'); ?></option>
89
- <?php
90
- $departments = wplc_get_all_deparments_mrg();
91
- if($departments){
92
- foreach($departments as $dep){
93
- ?>
94
- <option value="<?php echo $dep->id;?>" <?php echo ($selected_department === intval($dep->id) ? "SELECTED" : "" ); ?> ><?php echo sanitize_text_field($dep->name); ?></option>
95
- <?php
96
- }
97
- }
98
- ?>
99
- </select>
100
- </td>
101
- </tr>
102
- </table>
103
- <?php
104
- }
105
- }
106
  }
107
 
108
  add_action("wplc_pro_set_user_hook", "wplc_mrg_department_save", 10, 1);
73
  * @return void
74
  */
75
  function wplc_mrg_department_user_profile_departments($user){
76
+ if (wplc_user_is_agent($user->ID)) {
77
+ $selected_department = intval(get_user_meta($user->ID, "wplc_user_department", true));
78
+ if (current_user_can('manage_options', array(null))) {
79
+ ?>
80
+ <table class="form-table">
81
+ <tr>
82
+ <th>
83
+ <label for="wplc_user_department"><?php _e('Chat Department', 'wp-live-chat-support'); ?></label>
84
+ </th>
85
+ <td>
86
+ <select id="wplc_user_department" name="wplc_user_department">
87
+ <option value="-1"><?php _e("No Department", 'wp-live-chat-support'); ?></option>
88
+ <?php
89
+ $departments = wplc_get_all_deparments_mrg();
90
+ if ($departments) {
91
+ foreach($departments as $dep) {
92
+ ?>
93
+ <option value="<?php echo $dep->id;?>" <?php echo ($selected_department === intval($dep->id) ? "SELECTED" : "" ); ?> ><?php echo sanitize_text_field($dep->name); ?></option>
94
+ <?php
95
+ }
96
+ }
97
+ ?>
98
+ </select>
99
+ </td>
100
+ </tr>
101
+ </table>
102
+ <?php
103
+ }
104
+ }
 
105
  }
106
 
107
  add_action("wplc_pro_set_user_hook", "wplc_mrg_department_save", 10, 1);
includes/wplc_transfer_chats.php CHANGED
@@ -1,10 +1,10 @@
1
- <?php
2
  /*
3
  * Handles the transferring of a chat
4
  */
5
 
6
- if ( ! defined( 'ABSPATH' ) ) {
7
- exit;
8
  }
9
 
10
  add_filter("wplc_admin_chat_area_before_end_chat_button", "wplc_mrg_admin_transfer_tools", 15, 1);
@@ -12,9 +12,10 @@ add_filter("wplc_admin_chat_area_before_end_chat_button", "wplc_mrg_admin_transf
12
  * Outputs (echo) the 'Transfer' button
13
  *
14
  * @return void
15
- */
16
- function wplc_mrg_admin_transfer_tools($chat_data){
17
- echo wplc_create_modal_trigger_button_open("transfer", __("Transfer", 'wp-live-chat-support'));
 
18
  }
19
 
20
 
@@ -23,88 +24,89 @@ add_filter("wplc_hook_admin_below_chat_box", "wplc_mrg_admin_transfer_tools_moda
23
  * Outputs (echo) the 'Transfer' modal
24
  *
25
  * @return void
26
- */
27
- function wplc_mrg_admin_transfer_tools_modals($chat_data){
28
- if(function_exists('wplc_create_modal_window')){
29
- echo wplc_create_modal_window("transfer", __("Transfer Chat", 'wp-live-chat-support'), wplc_mrg_admin_transfer_tools_modal_content($chat_data));
30
-
31
- wplc_mrg_admin_transfer_tools_css();
32
- wplc_mrg_admin_transfer_tools_js();
33
- }
 
34
  }
35
 
36
  /**
37
  * Returns content for the transfer Modal
38
  *
39
  * @return string (html)
40
- */
41
- function wplc_mrg_admin_transfer_tools_modal_content($chat_data){
42
- $content = "<div id='wplc_transfer_modal_step_one_container'>";
43
- $content .= "<span>" . __("Would you like to transfer this chat to", 'wp-live-chat-support') . "</span><br><br>";
44
- $content .= "<a href='javascript:void(0);' class='button' id='wplc_pro_tranfer_to_agent_btn'>" . __("Agent", 'wp-live-chat-support') . "</a> ";
45
- $content .= "<a href='javascript:void(0);' class='button button-primary' id='wplc_pro_tranfer_to_department_btn'>" . __("Department", 'wp-live-chat-support') . "</a> ";
46
- $content .= "</div>";
47
-
48
- $content .= "<div id='wplc_transfer_modal_step_two_container'>";
49
- $content .= "<div id='wplc_transfer_modal_step_two_agent'>";
50
- $content .= "<span>" . __("Please select an agent to transfer to", 'wp-live-chat-support') . "</span><br><br>";
51
- $content .= wplc_mrg_admin_transfer_agent_selection() . "<br><br>";
52
-
53
- $content .= "<span id='wplc_transfer_to_agent_check'></span>";
54
-
55
- $content .= "</div>";
56
- $content .= "<div id='wplc_transfer_modal_step_two_department'>";
57
- $content .= "<span>" . __("Please select a department to transfer to", 'wp-live-chat-support') . "</span><br><br>";
58
- $content .= wplc_mrg_admin_transfer_department_selection() . "<br><br>";
59
-
60
- $content .= "<span id='wplc_transfer_to_department_check'></span>";
61
-
62
- $content .= "</div>";
63
- $content .= "</div>";
64
-
65
- return $content;
 
66
  }
67
 
68
  /**
69
  * Returns dropdown (html) of all online agent
70
  *
71
  * @return string (html)
72
- */
73
- function wplc_mrg_admin_transfer_agent_selection(){
74
- $content = "<select id='wplc_transfer_modal_agent_selection'>";
75
- $content .= "<option value=''>" . __("No Agent", 'wp-live-chat-support') . "</option>";
76
- $my_id = get_current_user_id();
77
- $user_array = get_users(array(
78
- 'meta_key'=> 'wplc_chat_agent_online',
79
- ));
80
- foreach($user_array as $user){
81
- $content .= "<option value='" . $user->ID . "'>" . $user->display_name . ($user->ID == $my_id ? "(" . __("You", 'wp-live-chat-support') . ")" : "") . "</option>";
82
- }
83
-
84
- $content .= "<select>";
85
- return $content;
86
  }
87
 
88
  /**
89
  * Returns dropdown (html) of all departments agent
90
  *
91
  * @return string (html)
92
- */
93
- function wplc_mrg_admin_transfer_department_selection(){
94
- if(function_exists("wplc_get_all_deparments_mrg")){
95
- $content = "<select id='wplc_transfer_modal_department_selection'>";
96
- $content .= "<option value='-1'>" . __("No Department", 'wp-live-chat-support') . "</option>";
97
- $departments = wplc_get_all_deparments_mrg();
98
- if($departments){
99
- foreach($departments as $dep){
100
- $content .= "<option value=" . $dep->id . ">" . $dep->name . "</option>";
101
- }
102
- }
103
- $content .= "<select>";
104
- } else {
105
- $content = "Version error";
106
- }
107
- return $content;
 
108
  }
109
 
110
 
@@ -112,180 +114,181 @@ function wplc_mrg_admin_transfer_department_selection(){
112
  * Outputs inline JavaScript for Transfer Modal
113
  *
114
  * @return void
115
- */
116
- function wplc_mrg_admin_transfer_tools_js(){
117
- ?>
118
- <script>
119
- var wplc_to_agent = null;
120
- var wplc_online_check_complete = false;
121
-
122
- var wplc_transfer_checking_agent_string = "<?php _e('Checking if agent is online', 'wp-live-chat-support'); ?>";
123
- var wplc_transfer_error_agent_string = "<?php _e('Agent is not online, transfer cannot be made', 'wp-live-chat-support'); ?>";
124
-
125
- var wplc_transfer_checking_department_string = "<?php _e('Checking if agents in department are online', 'wp-live-chat-support'); ?>";
126
- var wplc_transfer_error_department_string = "<?php _e('No agent within the department are available to accept the transfer, transfer cannot be made', 'wp-live-chat-support'); ?>";
127
-
128
- var wplc_transfer_success_string = "<?php _e('Agent(s) available, safe to transfer', 'wp-live-chat-support'); ?>";
129
-
130
- var wplc_transfer_complete_string = "<?php _e('Transfer Complete. Closing Window...', 'wp-live-chat-support'); ?>";
131
- var wplc_transfer_fail_string = "<?php _e('Transfer Failed. Please try again later...', 'wp-live-chat-support'); ?>";
132
-
133
- jQuery(function(){
134
- if(typeof wplc_modal_initialize !== "undefined" && typeof wplc_modal_initialize === "function"){
135
- wplc_modal_initialize(wplc_modal_transfer_open_modal, wplc_modal_transfer_confirm, wplc_modal_transfer_cancel, false);
136
- }
137
-
138
- jQuery("body").on("click", "#wplc_pro_tranfer_to_agent_btn", function(){
139
- jQuery("#wplc_transfer_modal_step_one_container").hide();
140
- jQuery("#wplc_transfer_modal_step_two_container").show();
141
- jQuery("#wplc_transfer_modal_step_two_agent").show();
142
- jQuery("#wplc_modal_inner_actions_transfer").show();
143
- wplc_to_agent = true;
144
- });
145
-
146
- jQuery("body").on("click", "#wplc_pro_tranfer_to_department_btn", function(){
147
- jQuery("#wplc_transfer_modal_step_one_container").hide();
148
- jQuery("#wplc_transfer_modal_step_two_container").show();
149
- jQuery("#wplc_modal_inner_actions_transfer").show();
150
- jQuery("#wplc_transfer_modal_step_two_department").show();
151
- wplc_to_agent = false;
152
- });
153
-
154
- jQuery("body").on("change", "#wplc_transfer_modal_agent_selection", function(){
155
- wplc_online_check_complete = false;
156
- jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
157
- jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
158
- jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_checking_agent_string);
159
- wplc_modal_transfer_check_online_agent(function(){
160
- wplc_online_check_complete = true;
161
- jQuery("#wplc_modal_confirm_transfer").removeClass("button-disabled");
162
- jQuery("#wplc_modal_confirm_transfer").addClass("button-primary");
163
- jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_success_string);
164
- }, function(){
165
- jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_error_agent_string);
166
- });
167
-
168
- });
169
-
170
- jQuery("body").on("change", "#wplc_transfer_modal_department_selection", function(){
171
- wplc_online_check_complete = false;
172
- jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
173
- jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
174
- jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_checking_department_string);
175
- wplc_modal_transfer_check_online_department(function(){
176
- wplc_online_check_complete = true;
177
- jQuery("#wplc_modal_confirm_transfer").removeClass("button-disabled");
178
- jQuery("#wplc_modal_confirm_transfer").addClass("button-primary");
179
- jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_success_string);
180
- }, function(){
181
- jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_error_department_string);
182
- });
183
- });
184
- });
185
-
186
- function wplc_modal_transfer_open_modal(){
187
- jQuery("#wplc_transfer_modal_step_one_container").show();
188
- jQuery("#wplc_transfer_modal_step_two_container").hide();
189
- jQuery("#wplc_modal_inner_actions_transfer").hide();
190
- jQuery("#wplc_transfer_modal_step_two_agent").hide();
191
- jQuery("#wplc_transfer_modal_step_two_department").hide();
192
- jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
193
- jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
194
-
195
- jQuery("#wplc_transfer_to_agent_check").text("");
196
- jQuery("#wplc_transfer_to_department_check").text("");
197
-
198
- wplc_to_agent = null;
199
- wplc_online_check_complete = false;
200
- }
201
-
202
- function wplc_modal_transfer_check_online_agent(check_success_callback, check_fail_callback){
203
- var aid = jQuery("#wplc_transfer_modal_agent_selection").val();
204
-
205
- var data ={
206
- action : "wplc_admin_transfer_check_agent_online",
207
- agent_id : parseInt(aid)
208
- };
209
-
210
- wplc_modal_transfer_ajax(data, function(return_data){
211
- if(return_data == "true"){
212
- if(typeof check_success_callback === "function"){
213
- check_success_callback();
214
- }
215
- } else {
216
- if(typeof check_fail_callback === "function"){
217
- check_fail_callback();
218
- }
219
- }
220
- }, function(){
221
- if(typeof check_fail_callback === "function"){
222
- check_fail_callback();
223
- }
224
- });
225
-
226
-
227
- }
228
-
229
- function wplc_modal_transfer_check_online_department(check_success_callback, check_fail_callback){
230
- var depid = jQuery("#wplc_transfer_modal_department_selection").val();
231
-
232
- var data ={
233
- action : "wplc_admin_transfer_check_department_online",
234
- dep_id : parseInt(depid)
235
- };
236
-
237
- wplc_modal_transfer_ajax(data, function(return_data){
238
- if(return_data == "true"){
239
- if(typeof check_success_callback === "function"){
240
- check_success_callback();
241
- }
242
- } else {
243
- if(typeof check_fail_callback === "function"){
244
- check_fail_callback();
245
- }
246
- }
247
- }, function(){
248
- if(typeof check_fail_callback === "function"){
249
- check_fail_callback();
250
- }
251
- });
252
- }
 
253
 
254
  function wplc_modal_transfer_ajax(req_data, on_succcess, on_error) {
255
  jQuery.ajax({
256
- url : "<?php echo admin_url('admin-ajax.php'); ?>",
257
- type : 'POST',
258
- data : req_data,
259
- success : function(return_data) {
260
- if(typeof on_succcess === "function"){
261
- on_succcess(return_data);
262
  }
263
  },
264
- error : function (){
265
- if(typeof on_error === "function"){
266
- on_error();
267
  }
268
  }
269
  });
270
  }
271
 
272
  function wplc_modal_transfer_confirm() {
273
- if(wplc_online_check_complete) {
274
- if(wplc_to_agent !== null) {
275
  <?php
276
  $cid = intval($_GET['cid']);
277
- ?>
278
- if(wplc_to_agent == true) {
279
  //Send to agent
280
  var aid = jQuery("#wplc_transfer_modal_agent_selection").val();
281
  var data = {
282
- action : "wplc_admin_transfer_to_agent",
283
- cid : parseInt("<?php echo $cid; ?>"),
284
- agent_id : parseInt(aid)
285
  };
286
-
287
- wplc_modal_transfer_ajax(data, function(return_data){
288
- if(return_data == "true") {
289
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_complete_string);
290
  setTimeout(function() {
291
  window.close();
@@ -293,20 +296,20 @@ function wplc_mrg_admin_transfer_tools_js(){
293
  } else {
294
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_fail_string);
295
  }
296
- }, function(){
297
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_fail_string);
298
  });
299
  } else {
300
  //Send to department
301
  var depid = jQuery("#wplc_transfer_modal_department_selection").val();
302
  var data = {
303
- action : "wplc_admin_transfer_to_department",
304
- cid : parseInt("<?php echo $cid; ?>"),
305
- dep_id : parseInt(depid)
306
  };
307
 
308
- wplc_modal_transfer_ajax(data, function(return_data){
309
- if(return_data == "true") {
310
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_complete_string);
311
  setTimeout(function() {
312
  window.close();
@@ -314,7 +317,7 @@ function wplc_mrg_admin_transfer_tools_js(){
314
  } else {
315
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_fail_string);
316
  }
317
- }, function(){
318
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_fail_string);
319
  });
320
  }
@@ -324,27 +327,29 @@ function wplc_mrg_admin_transfer_tools_js(){
324
  }
325
  }
326
 
327
- function wplc_modal_transfer_cancel(){
328
- wplc_to_agent = null;
329
- wplc_online_check_complete = false;
330
- }
331
- </script>
332
- <?php
333
  }
334
 
335
  /**
336
  * Outputs inline css for Transfer Modal
337
  *
338
  * @return void
339
- */
340
- function wplc_mrg_admin_transfer_tools_css(){
341
- ?>
342
- <style>
343
- #wplc_transfer_modal_step_one_container, #wplc_transfer_modal_step_two_container{
344
- text-align: center;
345
- }
346
- </style>
347
- <?php
 
 
348
  }
349
 
350
  add_filter("wplc_accept_chat_button_filter", "wplc_mrg_admin_accept_chat_button_text", 10, 2);
@@ -352,44 +357,45 @@ add_filter("wplc_accept_chat_button_filter", "wplc_mrg_admin_accept_chat_button_
352
  * Changes 'Accept Chat' to 'Accept Transfer'
353
  *
354
  * @return string
355
- */
356
- function wplc_mrg_admin_accept_chat_button_text($content, $cid){
357
- $chat_data = wplc_get_chat_data($cid, __LINE__);
358
- $max_wait_time = 60; //60 Seconds
359
- if (isset($chat_data->other)) {
360
- $other_data = maybe_unserialize( $chat_data->other );
361
- if( (isset($other_data['transfer']) && $other_data['transfer'] == true)){
362
- if(isset($chat_data->agent_id) && intval($chat_data->agent_id) !== 0){
363
- //For a specific agent
364
- if(isset($other_data['agent_transfer_time'])){
365
- //Check the time difference
366
- $seconds = time() - $other_data['agent_transfer_time'];
367
- if(intval($seconds) > $max_wait_time){
368
- do_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", $cid, $chat_data->agent_id);
369
- }
370
- }
371
-
372
- $agent_info = get_userdata(intval($chat_data->agent_id));
373
-
374
- return __("Transfer for", 'wp-live-chat-support') . " " . $agent_info->display_name;
375
- } else {
376
- //Department
377
- return __("Accept Transfer", 'wp-live-chat-support');
378
- }
379
- } else if ( (isset($other_data['unanswered']) && $other_data['unanswered'] == true) ){
380
- // Initial chat request -> Should still check timer
381
- if(isset($other_data['agent_transfer_time'])){
382
- //Check the time difference
383
- $seconds = time() - $other_data['agent_transfer_time'];
384
- if(intval($seconds) > $max_wait_time){
385
- do_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", $cid, -1); //Transfer to the next agent
386
- }
387
- }
388
- return $content;
389
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  }
 
391
 
392
- return $content;
393
  }
394
 
395
  add_filter("wplc_start_chat_hook_other_data_hook", "wplc_mrg_admin_transfer_add_initial_transfer_time", 10, 1);
@@ -397,10 +403,11 @@ add_filter("wplc_start_chat_hook_other_data_hook", "wplc_mrg_admin_transfer_add_
397
  * Adds an initial 'agent transfer time' value to the other data of the chat - On Chat Request
398
  *
399
  * @return array
400
- */
401
- function wplc_mrg_admin_transfer_add_initial_transfer_time($other_data){
402
- $other_data['agent_transfer_time'] = time();
403
- return $other_data;
 
404
  }
405
 
406
  add_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", "wplc_mrg_admin_transfer_to_next_available_agent", 10, 2);
@@ -408,225 +415,226 @@ add_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", "wplc_mrg_admin
408
  * Transfers chat to the next available agetn
409
  *
410
  * @return void
411
- */
412
- function wplc_mrg_admin_transfer_to_next_available_agent($chat_id, $current_agent){
413
- $chat_id = intval($chat_id);
414
- $current_agent = intval($current_agent);
415
-
416
- //Find all online agents
417
- $user_array = get_users(array(
418
- 'meta_key'=> 'wplc_chat_agent_online',
419
- ));
420
- $identified_candidate = false;
421
-
422
- foreach ($user_array as $user) {
423
- if($identified_candidate === false){
424
- if($current_agent !== $user->ID){
425
- $identified_candidate = $user->ID;
426
- }
427
- }
428
- }
429
-
430
- if($identified_candidate !== false){
431
- wplc_mrg_admin_transfer_to_agent($chat_id, $identified_candidate, true);
432
- }
433
 
 
 
 
434
  }
435
 
436
 
437
- add_action("wplc_hook_chat_notification","wplc_filter_control_chat_notification_department_transfer_mrg",10,3);
438
  /**
439
  * Handles 'Transfer' system notification
440
  *
441
  * @return string
442
- */
443
- function wplc_filter_control_chat_notification_department_transfer_mrg($type,$cid,$data) {
 
444
  if ($type == "transfer") {
445
  global $wpdb;
446
  global $wplc_tblname_msgs;
447
  $user_info = get_userdata(intval($data['aid']));
448
  $agent = "";
449
- if ($user_info ) {
450
- $agent = $user_info->display_name;
451
- }
452
  if (isset($data["auto_transfer"]) && $data["auto_transfer"] == true) {
453
  if (intval($data['aid']) === 0) {
454
  //Came from a department originally
455
- $msg=__("Department took too long to respond, we are transferring this chat to the next available agent.",'wp-live-chat-support');
456
  } else {
457
- $msg = $agent." ".__("took too long to respond, we are transferring this chat to the next available agent.",'wp-live-chat-support');
458
  }
459
  } else {
460
- $msg = $agent." ".__("has transferred the chat.",'wp-live-chat-support');
461
  }
462
 
463
  $wpdb->insert( // for user
464
- $wplc_tblname_msgs,
465
- array(
466
- 'chat_sess_id' => $cid,
467
  'timestamp' => current_time('mysql'),
468
- 'msgfrom' => __('System notification','wp-live-chat-support'),
469
  'msg' => $msg,
470
  'status' => 0,
471
  'originates' => 0
472
- ),
473
- array(
474
- '%s',
475
  '%s',
476
  '%s',
477
  '%s',
478
  '%d',
479
  '%d'
480
- )
481
  );
482
 
483
- $msg="*".__("User received this message", 'wp-live-chat-support') . ":* ".$msg;
484
  $wpdb->insert( // for agent
485
- $wplc_tblname_msgs,
486
- array(
487
- 'chat_sess_id' => $cid,
488
  'timestamp' => current_time('mysql'),
489
- 'msgfrom' => __('System notification','wp-live-chat-support'),
490
  'msg' => $msg,
491
  'status' => 0,
492
  'originates' => 3
493
- ),
494
- array(
495
- '%s',
496
  '%s',
497
  '%s',
498
  '%s',
499
  '%d',
500
  '%d'
501
- )
502
  );
503
  }
504
  }
505
 
506
- add_action("wplc_hook_chat_notification","wplc_filter_control_chat_notification_auto_department_transfer_mrg",10,3);
507
  /**
508
  * Handles 'Transfer' system notification
509
  *
510
  * @return string
511
- */
512
- function wplc_filter_control_chat_notification_auto_department_transfer_mrg($type,$cid,$data) {
513
- if ($type == "system_dep_transfer") {
514
- global $wpdb;
515
- global $wplc_tblname_msgs;
516
-
517
- $from_department = null;
518
- $to_department = null;
519
-
520
- if(isset($data['to_dep_id']) && isset($data['from_dep_id'])){
521
- if(function_exists("wplc_get_department_mrg")){
522
- $from_department = wplc_get_department_mrg(intval($data['from_dep_id']));
523
- $to_department = wplc_get_department_mrg(intval($data['to_dep_id']));
524
- }
525
- }
526
 
 
 
527
 
528
- $msg = __("No agents available in",'wp-live-chat-support') . " ";
529
- if($from_department === null){
530
- $msg .= __("selected department", 'wp-live-chat-support');
531
- } else {
532
- if(!empty($from_department[0]) && !empty($from_department[0]->name)){
533
- $msg .= $from_department[0]->name;
534
- }
535
- }
536
- $msg .= ", " . __("automatically transferring you to", 'wp-live-chat-support') . " ";
537
- if($to_department === null){
538
- $msg .= __("the next available department", 'wp-live-chat-support');
539
- } else {
540
- if(!empty($to_department[0]) && !empty($to_department[0]->name)){
541
- $msg .= $to_department[0]->name;
542
- }
543
- }
544
- $msg .= ".";
545
-
546
- $wpdb->insert(
547
- $wplc_tblname_msgs,
548
- array(
549
- 'chat_sess_id' => $cid,
550
- 'timestamp' => current_time('mysql'),
551
- 'msgfrom' => __('System notification','wp-live-chat-support'),
552
- 'msg' => $msg,
553
- 'status' => 0,
554
- 'originates' => 0
555
- ),
556
- array(
557
- '%s',
558
- '%s',
559
- '%s',
560
- '%s',
561
- '%d',
562
- '%d'
563
- )
564
- );
565
-
566
- $msg = __("User has been transferred from",'wp-live-chat-support') . " ";
567
- if($from_department === null){
568
- $msg .= __("department", 'wp-live-chat-support');
569
- } else {
570
- if(!empty($from_department[0]) && !empty($from_department[0]->name)){
571
- $msg .= $from_department[0]->name;
572
- }
573
- }
574
 
575
- if($to_department !== null){
576
- if(!empty($to_department[0]) && !empty($to_department[0]->name)){
577
- $msg .= ' '.__("to", 'wp-live-chat-support') . " " . $to_department[0]->name;
578
- }
579
- }
580
- $msg .= " " . __("as there were no agents online") . ".";
581
-
582
- $wpdb->insert(
583
- $wplc_tblname_msgs,
584
- array(
585
- 'chat_sess_id' => $cid,
586
- 'timestamp' => current_time('mysql'),
587
- 'msgfrom' => __('System notification','wp-live-chat-support'),
588
- 'msg' => $msg,
589
- 'status' => 0,
590
- 'originates' => 3
591
- ),
592
- array(
593
- '%s',
594
- '%s',
595
- '%s',
596
- '%s',
597
- '%d',
598
- '%d'
599
- )
600
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
  }
602
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
  }
604
 
605
- add_action("wplc_hook_change_status_on_answer","wplc_mrg_clear_transfer_request_if_set",10,2);
606
  /**
607
  * Unsets the transfer request once it is answered
608
  *
609
  * @return int (response code)
610
- */
611
- function wplc_mrg_clear_transfer_request_if_set($get_data, $chat_data = false) {
612
- global $wpdb;
613
- global $wplc_tblname_chats;
614
-
615
- $chat_id = intval($get_data['cid']);
616
- if (!$chat_data) { $chat_data = wplc_get_chat_data($chat_id, __LINE__); }
617
-
618
- if (isset($chat_data->other)) {
619
- $other_data = maybe_unserialize( $chat_data->other );
620
- if(isset( $other_data['transfer'] ) && $other_data['transfer'] == true){
621
- unset($other_data['transfer']);
622
- unset($other_data['unanswered']);
623
- unset($other_data['agent_transfer_time']);
624
-
625
- $new_chat_data = array('other' => maybe_serialize($other_data));
626
-
627
- $wpdb->update( $wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%s'), array('%d'));
628
- }
 
 
629
  }
 
630
  }
631
 
632
  add_filter("wplc_pro_department_update_filter", "wplc_mrg_admin_transfer_department_online_check", 10, 2);
@@ -634,40 +642,38 @@ add_filter("wplc_pro_department_update_filter", "wplc_mrg_admin_transfer_departm
634
  * Unsets the transfer request once it is answered
635
  *
636
  * @return int (response code)
637
- */
638
- function wplc_mrg_admin_transfer_department_online_check($department_id, $cid) {
639
- $search_department = intval($department_id);
640
- $user_array = get_users(array(
641
- 'meta_key'=> 'wplc_chat_agent_online',
642
- ));
643
-
644
- $fallback_department = null; //First agent who is online will be responsible for fallback
645
-
646
- $check = false;
647
- foreach($user_array as $user){
648
- $this_user_department = get_user_meta($user->ID, "wplc_user_department", true);
649
- if(intval($this_user_department == -1) || $this_user_department === ""){
650
- $check = true;
651
- } else if(intval($this_user_department) === $search_department){
652
- $check = true;
653
- }
654
-
655
- if($fallback_department === null){
656
- $fallback_department = $this_user_department;
657
- }
658
- }
659
-
660
- if($check){
661
- return $department_id; //Someone is online in this department, or a global department
662
- } else {
663
- if($fallback_department !== null){
664
- wplc_record_chat_notification("system_dep_transfer",$cid, array("from_dep_id" => $department_id, "to_dep_id" => $fallback_department));
665
- return $fallback_department;
666
- } else {
667
- //Joh.... This is broken
668
- return $department_id; //Just return the department ID passed in originally, hope for the best
669
- }
670
- }
671
  }
672
 
673
  /**
@@ -676,35 +682,36 @@ function wplc_mrg_admin_transfer_department_online_check($department_id, $cid) {
676
  * @param int $chat_id Chat ID
677
  * @param int $agent_id Agent ID
678
  * @return boolean
679
- */
680
- function wplc_mrg_admin_transfer_to_agent($chat_id, $agent_id, $auto_transfer){
681
- global $wpdb;
682
- global $wplc_tblname_chats;
683
-
684
- $chat_data = wplc_get_chat_data($chat_id, __LINE__);
685
- if (isset($chat_data->other)) {
686
- $other_data = maybe_unserialize( $chat_data->other );
687
- $other_data['unanswered'] = true;
688
- $other_data['transfer'] = true;
689
- $other_data['agent_transfer_time'] = time();
690
-
691
- $user_department = get_user_meta($agent_id, "wplc_user_department", true);
692
- if(!$user_department || $user_department === ""){
693
- $user_department = 0;
694
- }
 
695
 
696
- $new_chat_data = array('status' => 2, 'agent_id' => $agent_id, 'department_id' => $user_department,'other' => maybe_serialize($other_data));
697
 
698
- if($wpdb->update( $wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%d', '%d', '%d','%s'), array('%d'))){
699
- if(function_exists("wplc_record_chat_notification")){
700
- wplc_record_chat_notification("transfer", $chat_id, array("aid" => $chat_data->agent_id, "auto_transfer" => $auto_transfer));
701
- }
702
- return true;
703
- } else {
704
- return false;
705
- }
706
  }
707
- return false;
 
708
  }
709
 
710
  /**
@@ -713,30 +720,31 @@ function wplc_mrg_admin_transfer_to_agent($chat_id, $agent_id, $auto_transfer){
713
  * @param int $chat_id Chat ID
714
  * @param int $dep_id Department ID
715
  * @return boolean
716
- */
717
- function wplc_mrg_admin_transfer_to_department($chat_id, $dep_id){
718
- global $wpdb;
719
- global $wplc_tblname_chats;
720
-
721
- $chat_data = wplc_get_chat_data($chat_id, __LINE__);
722
- if (isset($chat_data->other)) {
723
- $other_data = maybe_unserialize( $chat_data->other );
724
- $other_data['unanswered'] = true;
725
- $other_data['transfer'] = true;
726
-
727
- $new_chat_data = array('status' => 2, 'agent_id' => 0, 'department_id' => $dep_id,'other' => maybe_serialize($other_data));
728
-
729
- if($wpdb->update( $wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%d', '%d', '%d','%s'), array('%d'))){
730
- if(function_exists("wplc_record_chat_notification")){
731
- wplc_record_chat_notification("transfer", $chat_id, array("aid" => $chat_data->agent_id));
732
- }
733
- return true;
734
- } else {
735
- return false;
736
- }
737
  }
 
738
 
739
- return false;
740
  }
741
 
742
  add_action('wp_ajax_wplc_admin_transfer_check_agent_online', 'wplc_mrg_admin_transfer_ajax');
@@ -747,75 +755,65 @@ add_action('wp_ajax_wplc_admin_transfer_to_department', 'wplc_mrg_admin_transfer
747
  * Handles the ajax calls for transfers
748
  *
749
  * @return string (response status)
750
- */
751
- function wplc_mrg_admin_transfer_ajax(){
752
- if(isset($_POST['action'])){
753
- if ($_POST['action'] == "wplc_admin_transfer_check_agent_online") {
754
- if(isset($_POST['agent_id'])){
755
- $user_id = intval($_POST['agent_id']);
756
- $check = get_user_meta($user_id, "wplc_chat_agent_online", true);
757
- if($check && $check !== ""){
758
- echo "true";
759
- exit();
760
- } else {
761
- echo "false"; //Agent no longer online
762
- exit();
763
- }
764
- }
765
- }
766
-
767
- if ($_POST['action'] == "wplc_admin_transfer_check_department_online") {
768
- if(isset($_POST['dep_id'])){
769
- $search_department = intval($_POST['dep_id']);
770
- $user_array = get_users(array(
771
- 'meta_key'=> 'wplc_chat_agent_online',
772
- ));
773
-
774
- $check = false;
775
-
776
- foreach($user_array as $user){
777
- $this_user_department = get_user_meta($user->ID, "wplc_user_department", true);
778
- if(intval($this_user_department) === $search_department){
779
- $check = true;
780
- }
781
- }
782
-
783
- if($check){
784
- echo "true";
785
- exit();
786
- } else {
787
- echo "false"; //Agent no longer online
788
- exit();
789
- }
790
- }
791
- }
792
-
793
- if ($_POST['action'] == "wplc_admin_transfer_to_agent") {
794
- if(isset($_POST['cid']) && isset($_POST['agent_id'])){
795
- $chat_id = intval($_POST['cid']);
796
- $agent_id = intval($_POST['agent_id']);
797
- if(wplc_mrg_admin_transfer_to_agent($chat_id, $agent_id, false)){
798
- echo "true";
799
- exit();
800
- } else {
801
- echo "false";
802
- exit();
803
- }
804
- }
805
- }
806
-
807
- if ($_POST['action'] == "wplc_admin_transfer_to_department") {
808
- if(isset($_POST['cid']) && isset($_POST['dep_id'])){
809
- $chat_id = intval($_POST['cid']);
810
- $dep_id = intval($_POST['dep_id']);
811
- if(wplc_mrg_admin_transfer_to_department($chat_id, $dep_id)){
812
- echo "true";
813
- exit();
814
- } else {
815
- echo "false";
816
- exit();
817
- }
818
- }
819
- }
820
- }
821
- }
1
+ <?php
2
  /*
3
  * Handles the transferring of a chat
4
  */
5
 
6
+ if (!defined('ABSPATH')) {
7
+ exit;
8
  }
9
 
10
  add_filter("wplc_admin_chat_area_before_end_chat_button", "wplc_mrg_admin_transfer_tools", 15, 1);
12
  * Outputs (echo) the 'Transfer' button
13
  *
14
  * @return void
15
+ */
16
+ function wplc_mrg_admin_transfer_tools($chat_data)
17
+ {
18
+ echo wplc_create_modal_trigger_button_open("transfer", __("Transfer", 'wp-live-chat-support'));
19
  }
20
 
21
 
24
  * Outputs (echo) the 'Transfer' modal
25
  *
26
  * @return void
27
+ */
28
+ function wplc_mrg_admin_transfer_tools_modals($chat_data)
29
+ {
30
+ if (function_exists('wplc_create_modal_window')) {
31
+ echo wplc_create_modal_window("transfer", __("Transfer Chat", 'wp-live-chat-support'), wplc_mrg_admin_transfer_tools_modal_content($chat_data));
32
+
33
+ wplc_mrg_admin_transfer_tools_css();
34
+ wplc_mrg_admin_transfer_tools_js();
35
+ }
36
  }
37
 
38
  /**
39
  * Returns content for the transfer Modal
40
  *
41
  * @return string (html)
42
+ */
43
+ function wplc_mrg_admin_transfer_tools_modal_content($chat_data)
44
+ {
45
+ $content = "<div id='wplc_transfer_modal_step_one_container'>";
46
+ $content .= "<span>" . __("Would you like to transfer this chat to", 'wp-live-chat-support') . "</span><br><br>";
47
+ $content .= "<a href='javascript:void(0);' class='button' id='wplc_pro_tranfer_to_agent_btn'>" . __("Agent", 'wp-live-chat-support') . "</a> ";
48
+ $content .= "<a href='javascript:void(0);' class='button button-primary' id='wplc_pro_tranfer_to_department_btn'>" . __("Department", 'wp-live-chat-support') . "</a> ";
49
+ $content .= "</div>";
50
+
51
+ $content .= "<div id='wplc_transfer_modal_step_two_container'>";
52
+ $content .= "<div id='wplc_transfer_modal_step_two_agent'>";
53
+ $content .= "<span>" . __("Please select an agent to transfer to", 'wp-live-chat-support') . "</span><br><br>";
54
+ $content .= wplc_mrg_admin_transfer_agent_selection() . "<br><br>";
55
+
56
+ $content .= "<span id='wplc_transfer_to_agent_check'></span>";
57
+
58
+ $content .= "</div>";
59
+ $content .= "<div id='wplc_transfer_modal_step_two_department'>";
60
+ $content .= "<span>" . __("Please select a department to transfer to", 'wp-live-chat-support') . "</span><br><br>";
61
+ $content .= wplc_mrg_admin_transfer_department_selection() . "<br><br>";
62
+
63
+ $content .= "<span id='wplc_transfer_to_department_check'></span>";
64
+
65
+ $content .= "</div>";
66
+ $content .= "</div>";
67
+
68
+ return $content;
69
  }
70
 
71
  /**
72
  * Returns dropdown (html) of all online agent
73
  *
74
  * @return string (html)
75
+ */
76
+ function wplc_mrg_admin_transfer_agent_selection()
77
+ {
78
+ $content = "<select id='wplc_transfer_modal_agent_selection'>";
79
+ $content .= "<option value=''>" . __("No Agent", 'wp-live-chat-support') . "</option>";
80
+ $my_id = get_current_user_id();
81
+ $user_array = wplc_get_online_agent_users();
82
+ foreach ($user_array as $user) {
83
+ $content .= "<option value='" . $user->ID . "'>" . $user->display_name . ($user->ID == $my_id ? "(" . __("You", 'wp-live-chat-support') . ")" : "") . "</option>";
84
+ }
85
+ $content .= "<select>";
86
+ return $content;
 
 
87
  }
88
 
89
  /**
90
  * Returns dropdown (html) of all departments agent
91
  *
92
  * @return string (html)
93
+ */
94
+ function wplc_mrg_admin_transfer_department_selection()
95
+ {
96
+ if (function_exists("wplc_get_all_deparments_mrg")) {
97
+ $content = "<select id='wplc_transfer_modal_department_selection'>";
98
+ $content .= "<option value='-1'>" . __("No Department", 'wp-live-chat-support') . "</option>";
99
+ $departments = wplc_get_all_deparments_mrg();
100
+ if ($departments) {
101
+ foreach ($departments as $dep) {
102
+ $content .= "<option value=" . $dep->id . ">" . $dep->name . "</option>";
103
+ }
104
+ }
105
+ $content .= "<select>";
106
+ } else {
107
+ $content = "Version error";
108
+ }
109
+ return $content;
110
  }
111
 
112
 
114
  * Outputs inline JavaScript for Transfer Modal
115
  *
116
  * @return void
117
+ */
118
+ function wplc_mrg_admin_transfer_tools_js()
119
+ {
120
+ ?>
121
+ <script>
122
+ var wplc_to_agent = null;
123
+ var wplc_online_check_complete = false;
124
+
125
+ var wplc_transfer_checking_agent_string = "<?php _e('Checking if agent is online', 'wp-live-chat-support'); ?>";
126
+ var wplc_transfer_error_agent_string = "<?php _e('Agent is not online, transfer cannot be made', 'wp-live-chat-support'); ?>";
127
+
128
+ var wplc_transfer_checking_department_string = "<?php _e('Checking if agents in department are online', 'wp-live-chat-support'); ?>";
129
+ var wplc_transfer_error_department_string = "<?php _e('No agent within the department are available to accept the transfer, transfer cannot be made', 'wp-live-chat-support'); ?>";
130
+
131
+ var wplc_transfer_success_string = "<?php _e('Agent(s) available, safe to transfer', 'wp-live-chat-support'); ?>";
132
+
133
+ var wplc_transfer_complete_string = "<?php _e('Transfer Complete. Closing Window...', 'wp-live-chat-support'); ?>";
134
+ var wplc_transfer_fail_string = "<?php _e('Transfer Failed. Please try again later...', 'wp-live-chat-support'); ?>";
135
+
136
+ jQuery(function() {
137
+ if (typeof wplc_modal_initialize !== "undefined" && typeof wplc_modal_initialize === "function") {
138
+ wplc_modal_initialize(wplc_modal_transfer_open_modal, wplc_modal_transfer_confirm, wplc_modal_transfer_cancel, false);
139
+ }
140
+
141
+ jQuery("body").on("click", "#wplc_pro_tranfer_to_agent_btn", function() {
142
+ jQuery("#wplc_transfer_modal_step_one_container").hide();
143
+ jQuery("#wplc_transfer_modal_step_two_container").show();
144
+ jQuery("#wplc_transfer_modal_step_two_agent").show();
145
+ jQuery("#wplc_modal_inner_actions_transfer").show();
146
+ wplc_to_agent = true;
147
+ });
148
+
149
+ jQuery("body").on("click", "#wplc_pro_tranfer_to_department_btn", function() {
150
+ jQuery("#wplc_transfer_modal_step_one_container").hide();
151
+ jQuery("#wplc_transfer_modal_step_two_container").show();
152
+ jQuery("#wplc_modal_inner_actions_transfer").show();
153
+ jQuery("#wplc_transfer_modal_step_two_department").show();
154
+ wplc_to_agent = false;
155
+ });
156
+
157
+ jQuery("body").on("change", "#wplc_transfer_modal_agent_selection", function() {
158
+ wplc_online_check_complete = false;
159
+ jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
160
+ jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
161
+ jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_checking_agent_string);
162
+ wplc_modal_transfer_check_online_agent(function() {
163
+ wplc_online_check_complete = true;
164
+ jQuery("#wplc_modal_confirm_transfer").removeClass("button-disabled");
165
+ jQuery("#wplc_modal_confirm_transfer").addClass("button-primary");
166
+ jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_success_string);
167
+ }, function() {
168
+ jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_error_agent_string);
169
+ });
170
+
171
+ });
172
+
173
+ jQuery("body").on("change", "#wplc_transfer_modal_department_selection", function() {
174
+ wplc_online_check_complete = false;
175
+ jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
176
+ jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
177
+ jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_checking_department_string);
178
+ wplc_modal_transfer_check_online_department(function() {
179
+ wplc_online_check_complete = true;
180
+ jQuery("#wplc_modal_confirm_transfer").removeClass("button-disabled");
181
+ jQuery("#wplc_modal_confirm_transfer").addClass("button-primary");
182
+ jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_success_string);
183
+ }, function() {
184
+ jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_error_department_string);
185
+ });
186
+ });
187
+ });
188
+
189
+ function wplc_modal_transfer_open_modal() {
190
+ jQuery("#wplc_transfer_modal_step_one_container").show();
191
+ jQuery("#wplc_transfer_modal_step_two_container").hide();
192
+ jQuery("#wplc_modal_inner_actions_transfer").hide();
193
+ jQuery("#wplc_transfer_modal_step_two_agent").hide();
194
+ jQuery("#wplc_transfer_modal_step_two_department").hide();
195
+ jQuery("#wplc_modal_confirm_transfer").removeClass("button-primary");
196
+ jQuery("#wplc_modal_confirm_transfer").addClass("button-disabled");
197
+
198
+ jQuery("#wplc_transfer_to_agent_check").text("");
199
+ jQuery("#wplc_transfer_to_department_check").text("");
200
+
201
+ wplc_to_agent = null;
202
+ wplc_online_check_complete = false;
203
+ }
204
+
205
+ function wplc_modal_transfer_check_online_agent(check_success_callback, check_fail_callback) {
206
+ var aid = jQuery("#wplc_transfer_modal_agent_selection").val();
207
+
208
+ var data = {
209
+ action: "wplc_admin_transfer_check_agent_online",
210
+ agent_id: parseInt(aid)
211
+ };
212
+
213
+ wplc_modal_transfer_ajax(data, function(return_data) {
214
+ if (return_data == "true") {
215
+ if (typeof check_success_callback === "function") {
216
+ check_success_callback();
217
+ }
218
+ } else {
219
+ if (typeof check_fail_callback === "function") {
220
+ check_fail_callback();
221
+ }
222
+ }
223
+ }, function() {
224
+ if (typeof check_fail_callback === "function") {
225
+ check_fail_callback();
226
+ }
227
+ });
228
+
229
+
230
+ }
231
+
232
+ function wplc_modal_transfer_check_online_department(check_success_callback, check_fail_callback) {
233
+ var depid = jQuery("#wplc_transfer_modal_department_selection").val();
234
+
235
+ var data = {
236
+ action: "wplc_admin_transfer_check_department_online",
237
+ dep_id: parseInt(depid)
238
+ };
239
+
240
+ wplc_modal_transfer_ajax(data, function(return_data) {
241
+ if (return_data == "true") {
242
+ if (typeof check_success_callback === "function") {
243
+ check_success_callback();
244
+ }
245
+ } else {
246
+ if (typeof check_fail_callback === "function") {
247
+ check_fail_callback();
248
+ }
249
+ }
250
+ }, function() {
251
+ if (typeof check_fail_callback === "function") {
252
+ check_fail_callback();
253
+ }
254
+ });
255
+ }
256
 
257
  function wplc_modal_transfer_ajax(req_data, on_succcess, on_error) {
258
  jQuery.ajax({
259
+ url: "<?php echo admin_url('admin-ajax.php'); ?>",
260
+ type: 'POST',
261
+ data: req_data,
262
+ success: function(return_data) {
263
+ if (typeof on_succcess === "function") {
264
+ on_succcess(return_data);
265
  }
266
  },
267
+ error: function() {
268
+ if (typeof on_error === "function") {
269
+ on_error();
270
  }
271
  }
272
  });
273
  }
274
 
275
  function wplc_modal_transfer_confirm() {
276
+ if (wplc_online_check_complete) {
277
+ if (wplc_to_agent !== null) {
278
  <?php
279
  $cid = intval($_GET['cid']);
280
+ ?>
281
+ if (wplc_to_agent == true) {
282
  //Send to agent
283
  var aid = jQuery("#wplc_transfer_modal_agent_selection").val();
284
  var data = {
285
+ action: "wplc_admin_transfer_to_agent",
286
+ cid: parseInt("<?php echo $cid; ?>"),
287
+ agent_id: parseInt(aid)
288
  };
289
+
290
+ wplc_modal_transfer_ajax(data, function(return_data) {
291
+ if (return_data == "true") {
292
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_complete_string);
293
  setTimeout(function() {
294
  window.close();
296
  } else {
297
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_fail_string);
298
  }
299
+ }, function() {
300
  jQuery("#wplc_transfer_to_agent_check").text(wplc_transfer_fail_string);
301
  });
302
  } else {
303
  //Send to department
304
  var depid = jQuery("#wplc_transfer_modal_department_selection").val();
305
  var data = {
306
+ action: "wplc_admin_transfer_to_department",
307
+ cid: parseInt("<?php echo $cid; ?>"),
308
+ dep_id: parseInt(depid)
309
  };
310
 
311
+ wplc_modal_transfer_ajax(data, function(return_data) {
312
+ if (return_data == "true") {
313
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_complete_string);
314
  setTimeout(function() {
315
  window.close();
317
  } else {
318
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_fail_string);
319
  }
320
+ }, function() {
321
  jQuery("#wplc_transfer_to_department_check").text(wplc_transfer_fail_string);
322
  });
323
  }
327
  }
328
  }
329
 
330
+ function wplc_modal_transfer_cancel() {
331
+ wplc_to_agent = null;
332
+ wplc_online_check_complete = false;
333
+ }
334
+ </script>
335
+ <?php
336
  }
337
 
338
  /**
339
  * Outputs inline css for Transfer Modal
340
  *
341
  * @return void
342
+ */
343
+ function wplc_mrg_admin_transfer_tools_css()
344
+ {
345
+ ?>
346
+ <style>
347
+ #wplc_transfer_modal_step_one_container,
348
+ #wplc_transfer_modal_step_two_container {
349
+ text-align: center;
350
+ }
351
+ </style>
352
+ <?php
353
  }
354
 
355
  add_filter("wplc_accept_chat_button_filter", "wplc_mrg_admin_accept_chat_button_text", 10, 2);
357
  * Changes 'Accept Chat' to 'Accept Transfer'
358
  *
359
  * @return string
360
+ */
361
+ function wplc_mrg_admin_accept_chat_button_text($content, $cid)
362
+ {
363
+ $chat_data = wplc_get_chat_data($cid, __LINE__);
364
+ $max_wait_time = 60; //60 Seconds
365
+ if (isset($chat_data->other)) {
366
+ $other_data = maybe_unserialize($chat_data->other);
367
+ if ((isset($other_data['transfer']) && $other_data['transfer'] == true)) {
368
+ if (isset($chat_data->agent_id) && intval($chat_data->agent_id) !== 0) {
369
+ //For a specific agent
370
+ if (isset($other_data['agent_transfer_time'])) {
371
+ //Check the time difference
372
+ $seconds = time() - $other_data['agent_transfer_time'];
373
+ if (intval($seconds) > $max_wait_time) {
374
+ do_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", $cid, $chat_data->agent_id);
375
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  }
377
+
378
+ $agent_info = get_userdata(intval($chat_data->agent_id));
379
+
380
+ return __("Transfer for", 'wp-live-chat-support') . " " . $agent_info->display_name;
381
+ } else {
382
+ //Department
383
+ return __("Accept Transfer", 'wp-live-chat-support');
384
+ }
385
+ } else if ((isset($other_data['unanswered']) && $other_data['unanswered'] == true)) {
386
+ // Initial chat request -> Should still check timer
387
+ if (isset($other_data['agent_transfer_time'])) {
388
+ //Check the time difference
389
+ $seconds = time() - $other_data['agent_transfer_time'];
390
+ if (intval($seconds) > $max_wait_time) {
391
+ do_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", $cid, -1); //Transfer to the next agent
392
+ }
393
+ }
394
+ return $content;
395
  }
396
+ }
397
 
398
+ return $content;
399
  }
400
 
401
  add_filter("wplc_start_chat_hook_other_data_hook", "wplc_mrg_admin_transfer_add_initial_transfer_time", 10, 1);
403
  * Adds an initial 'agent transfer time' value to the other data of the chat - On Chat Request
404
  *
405
  * @return array
406
+ */
407
+ function wplc_mrg_admin_transfer_add_initial_transfer_time($other_data)
408
+ {
409
+ $other_data['agent_transfer_time'] = time();
410
+ return $other_data;
411
  }
412
 
413
  add_action("wplc_pro_admin_transfer_agent_exceeded_accept_time", "wplc_mrg_admin_transfer_to_next_available_agent", 10, 2);
415
  * Transfers chat to the next available agetn
416
  *
417
  * @return void
418
+ */
419
+ function wplc_mrg_admin_transfer_to_next_available_agent($chat_id, $current_agent)
420
+ {
421
+ $chat_id = intval($chat_id);
422
+ $current_agent = intval($current_agent);
423
+ //Find all online agents
424
+ $user_array = wplc_get_online_agent_users();
425
+ $identified_candidate = false;
426
+ foreach ($user_array as $user) {
427
+ if ($identified_candidate === false) {
428
+ if ($current_agent !== $user->ID) {
429
+ $identified_candidate = $user->ID;
430
+ }
431
+ }
432
+ }
 
 
 
 
 
 
 
433
 
434
+ if ($identified_candidate !== false) {
435
+ wplc_mrg_admin_transfer_to_agent($chat_id, $identified_candidate, true);
436
+ }
437
  }
438
 
439
 
440
+ add_action("wplc_hook_chat_notification", "wplc_filter_control_chat_notification_department_transfer_mrg", 10, 3);
441
  /**
442
  * Handles 'Transfer' system notification
443
  *
444
  * @return string
445
+ */
446
+ function wplc_filter_control_chat_notification_department_transfer_mrg($type, $cid, $data)
447
+ {
448
  if ($type == "transfer") {
449
  global $wpdb;
450
  global $wplc_tblname_msgs;
451
  $user_info = get_userdata(intval($data['aid']));
452
  $agent = "";
453
+ if ($user_info) {
454
+ $agent = $user_info->display_name;
455
+ }
456
  if (isset($data["auto_transfer"]) && $data["auto_transfer"] == true) {
457
  if (intval($data['aid']) === 0) {
458
  //Came from a department originally
459
+ $msg = __("Department took too long to respond, we are transferring this chat to the next available agent.", 'wp-live-chat-support');
460
  } else {
461
+ $msg = $agent . " " . __("took too long to respond, we are transferring this chat to the next available agent.", 'wp-live-chat-support');
462
  }
463
  } else {
464
+ $msg = $agent . " " . __("has transferred the chat.", 'wp-live-chat-support');
465
  }
466
 
467
  $wpdb->insert( // for user
468
+ $wplc_tblname_msgs,
469
+ array(
470
+ 'chat_sess_id' => $cid,
471
  'timestamp' => current_time('mysql'),
472
+ 'msgfrom' => __('System notification', 'wp-live-chat-support'),
473
  'msg' => $msg,
474
  'status' => 0,
475
  'originates' => 0
476
+ ),
477
+ array(
478
+ '%s',
479
  '%s',
480
  '%s',
481
  '%s',
482
  '%d',
483
  '%d'
484
+ )
485
  );
486
 
487
+ $msg = "*" . __("User received this message", 'wp-live-chat-support') . ":* " . $msg;
488
  $wpdb->insert( // for agent
489
+ $wplc_tblname_msgs,
490
+ array(
491
+ 'chat_sess_id' => $cid,
492
  'timestamp' => current_time('mysql'),
493
+ 'msgfrom' => __('System notification', 'wp-live-chat-support'),
494
  'msg' => $msg,
495
  'status' => 0,
496
  'originates' => 3
497
+ ),
498
+ array(
499
+ '%s',
500
  '%s',
501
  '%s',
502
  '%s',
503
  '%d',
504
  '%d'
505
+ )
506
  );
507
  }
508
  }
509
 
510
+ add_action("wplc_hook_chat_notification", "wplc_filter_control_chat_notification_auto_department_transfer_mrg", 10, 3);
511
  /**
512
  * Handles 'Transfer' system notification
513
  *
514
  * @return string
515
+ */
516
+ function wplc_filter_control_chat_notification_auto_department_transfer_mrg($type, $cid, $data)
517
+ {
518
+ if ($type == "system_dep_transfer") {
519
+ global $wpdb;
520
+ global $wplc_tblname_msgs;
 
 
 
 
 
 
 
 
 
521
 
522
+ $from_department = null;
523
+ $to_department = null;
524
 
525
+ if (isset($data['to_dep_id']) && isset($data['from_dep_id'])) {
526
+ if (function_exists("wplc_get_department_mrg")) {
527
+ $from_department = wplc_get_department_mrg(intval($data['from_dep_id']));
528
+ $to_department = wplc_get_department_mrg(intval($data['to_dep_id']));
529
+ }
530
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
 
532
+
533
+ $msg = __("No agents available in", 'wp-live-chat-support') . " ";
534
+ if ($from_department === null) {
535
+ $msg .= __("selected department", 'wp-live-chat-support');
536
+ } else {
537
+ if (!empty($from_department[0]) && !empty($from_department[0]->name)) {
538
+ $msg .= $from_department[0]->name;
539
+ }
540
+ }
541
+ $msg .= ", " . __("automatically transferring you to", 'wp-live-chat-support') . " ";
542
+ if ($to_department === null) {
543
+ $msg .= __("the next available department", 'wp-live-chat-support');
544
+ } else {
545
+ if (!empty($to_department[0]) && !empty($to_department[0]->name)) {
546
+ $msg .= $to_department[0]->name;
547
+ }
548
+ }
549
+ $msg .= ".";
550
+
551
+ $wpdb->insert(
552
+ $wplc_tblname_msgs,
553
+ array(
554
+ 'chat_sess_id' => $cid,
555
+ 'timestamp' => current_time('mysql'),
556
+ 'msgfrom' => __('System notification', 'wp-live-chat-support'),
557
+ 'msg' => $msg,
558
+ 'status' => 0,
559
+ 'originates' => 0
560
+ ),
561
+ array(
562
+ '%s',
563
+ '%s',
564
+ '%s',
565
+ '%s',
566
+ '%d',
567
+ '%d'
568
+ )
569
+ );
570
+
571
+ $msg = __("User has been transferred from", 'wp-live-chat-support') . " ";
572
+ if ($from_department === null) {
573
+ $msg .= __("department", 'wp-live-chat-support');
574
+ } else {
575
+ if (!empty($from_department[0]) && !empty($from_department[0]->name)) {
576
+ $msg .= $from_department[0]->name;
577
+ }
578
+ }
579
+
580
+ if ($to_department !== null) {
581
+ if (!empty($to_department[0]) && !empty($to_department[0]->name)) {
582
+ $msg .= ' ' . __("to", 'wp-live-chat-support') . " " . $to_department[0]->name;
583
+ }
584
  }
585
+ $msg .= " " . __("as there were no agents online") . ".";
586
+
587
+ $wpdb->insert(
588
+ $wplc_tblname_msgs,
589
+ array(
590
+ 'chat_sess_id' => $cid,
591
+ 'timestamp' => current_time('mysql'),
592
+ 'msgfrom' => __('System notification', 'wp-live-chat-support'),
593
+ 'msg' => $msg,
594
+ 'status' => 0,
595
+ 'originates' => 3
596
+ ),
597
+ array(
598
+ '%s',
599
+ '%s',
600
+ '%s',
601
+ '%s',
602
+ '%d',
603
+ '%d'
604
+ )
605
+ );
606
+ }
607
+ return;
608
  }
609
 
610
+ add_action("wplc_hook_change_status_on_answer", "wplc_mrg_clear_transfer_request_if_set", 10, 2);
611
  /**
612
  * Unsets the transfer request once it is answered
613
  *
614
  * @return int (response code)
615
+ */
616
+ function wplc_mrg_clear_transfer_request_if_set($get_data, $chat_data = false)
617
+ {
618
+ global $wpdb;
619
+ global $wplc_tblname_chats;
620
+
621
+ $chat_id = intval($get_data['cid']);
622
+ if (!$chat_data) {
623
+ $chat_data = wplc_get_chat_data($chat_id, __LINE__);
624
+ }
625
+
626
+ if (isset($chat_data->other)) {
627
+ $other_data = maybe_unserialize($chat_data->other);
628
+ if (isset($other_data['transfer']) && $other_data['transfer'] == true) {
629
+ unset($other_data['transfer']);
630
+ unset($other_data['unanswered']);
631
+ unset($other_data['agent_transfer_time']);
632
+
633
+ $new_chat_data = array('other' => maybe_serialize($other_data));
634
+
635
+ $wpdb->update($wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%s'), array('%d'));
636
  }
637
+ }
638
  }
639
 
640
  add_filter("wplc_pro_department_update_filter", "wplc_mrg_admin_transfer_department_online_check", 10, 2);
642
  * Unsets the transfer request once it is answered
643
  *
644
  * @return int (response code)
645
+ */
646
+ function wplc_mrg_admin_transfer_department_online_check($department_id, $cid)
647
+ {
648
+ $search_department = intval($department_id);
649
+ $user_array = wplc_get_online_agent_users();
650
+ $fallback_department = null; //First agent who is online will be responsible for fallback
651
+
652
+ $check = false;
653
+ foreach ($user_array as $user) {
654
+ $this_user_department = get_user_meta($user->ID, "wplc_user_department", true);
655
+ if (intval($this_user_department == -1) || $this_user_department === "") {
656
+ $check = true;
657
+ } else if (intval($this_user_department) === $search_department) {
658
+ $check = true;
659
+ }
660
+
661
+ if ($fallback_department === null) {
662
+ $fallback_department = $this_user_department;
663
+ }
664
+ }
665
+
666
+ if ($check) {
667
+ return $department_id; //Someone is online in this department, or a global department
668
+ } else {
669
+ if ($fallback_department !== null) {
670
+ wplc_record_chat_notification("system_dep_transfer", $cid, array("from_dep_id" => $department_id, "to_dep_id" => $fallback_department));
671
+ return $fallback_department;
672
+ } else {
673
+ //Joh.... This is broken
674
+ return $department_id; //Just return the department ID passed in originally, hope for the best
675
+ }
676
+ }
 
 
677
  }
678
 
679
  /**
682
  * @param int $chat_id Chat ID
683
  * @param int $agent_id Agent ID
684
  * @return boolean
685
+ */
686
+ function wplc_mrg_admin_transfer_to_agent($chat_id, $agent_id, $auto_transfer)
687
+ {
688
+ global $wpdb;
689
+ global $wplc_tblname_chats;
690
+
691
+ $chat_data = wplc_get_chat_data($chat_id, __LINE__);
692
+ if (isset($chat_data->other)) {
693
+ $other_data = maybe_unserialize($chat_data->other);
694
+ $other_data['unanswered'] = true;
695
+ $other_data['transfer'] = true;
696
+ $other_data['agent_transfer_time'] = time();
697
+
698
+ $user_department = get_user_meta($agent_id, "wplc_user_department", true);
699
+ if (!$user_department || $user_department === "") {
700
+ $user_department = 0;
701
+ }
702
 
703
+ $new_chat_data = array('status' => 2, 'agent_id' => $agent_id, 'department_id' => $user_department, 'other' => maybe_serialize($other_data));
704
 
705
+ if ($wpdb->update($wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%d', '%d', '%d', '%s'), array('%d'))) {
706
+ if (function_exists("wplc_record_chat_notification")) {
707
+ wplc_record_chat_notification("transfer", $chat_id, array("aid" => $chat_data->agent_id, "auto_transfer" => $auto_transfer));
708
+ }
709
+ return true;
710
+ } else {
711
+ return false;
 
712
  }
713
+ }
714
+ return false;
715
  }
716
 
717
  /**
720
  * @param int $chat_id Chat ID
721
  * @param int $dep_id Department ID
722
  * @return boolean
723
+ */
724
+ function wplc_mrg_admin_transfer_to_department($chat_id, $dep_id)
725
+ {
726
+ global $wpdb;
727
+ global $wplc_tblname_chats;
728
+
729
+ $chat_data = wplc_get_chat_data($chat_id, __LINE__);
730
+ if (isset($chat_data->other)) {
731
+ $other_data = maybe_unserialize($chat_data->other);
732
+ $other_data['unanswered'] = true;
733
+ $other_data['transfer'] = true;
734
+
735
+ $new_chat_data = array('status' => 2, 'agent_id' => 0, 'department_id' => $dep_id, 'other' => maybe_serialize($other_data));
736
+
737
+ if ($wpdb->update($wplc_tblname_chats, $new_chat_data, array('id' => $chat_id), array('%d', '%d', '%d', '%s'), array('%d'))) {
738
+ if (function_exists("wplc_record_chat_notification")) {
739
+ wplc_record_chat_notification("transfer", $chat_id, array("aid" => $chat_data->agent_id));
740
+ }
741
+ return true;
742
+ } else {
743
+ return false;
744
  }
745
+ }
746
 
747
+ return false;
748
  }
749
 
750
  add_action('wp_ajax_wplc_admin_transfer_check_agent_online', 'wplc_mrg_admin_transfer_ajax');
755
  * Handles the ajax calls for transfers
756
  *
757
  * @return string (response status)
758
+ */
759
+ function wplc_mrg_admin_transfer_ajax() {
760
+ if (isset($_POST['action'])) {
761
+ if ($_POST['action'] == "wplc_admin_transfer_check_agent_online") {
762
+ if (isset($_POST['agent_id'])) {
763
+ $user_id = intval($_POST['agent_id']);
764
+ if (wplc_agent_is_online($user_id)) {
765
+ echo "true";
766
+ } else {
767
+ echo "false"; //Agent no longer online
768
+ }
769
+ }
770
+ exit();
771
+ }
772
+
773
+ if ($_POST['action'] == "wplc_admin_transfer_check_department_online") {
774
+ if (isset($_POST['dep_id'])) {
775
+ $search_department = intval($_POST['dep_id']);
776
+ $user_array = wplc_get_online_agent_users();
777
+ $check = false;
778
+ foreach ($user_array as $user) {
779
+ $this_user_department = get_user_meta($user->ID, "wplc_user_department", true);
780
+ if (intval($this_user_department) === $search_department) {
781
+ $check = true;
782
+ }
783
+ }
784
+ if ($check) {
785
+ echo "true";
786
+ } else {
787
+ echo "false"; //Agent no longer online
788
+ }
789
+ }
790
+ exit();
791
+ }
792
+
793
+ if ($_POST['action'] == "wplc_admin_transfer_to_agent") {
794
+ if (isset($_POST['cid']) && isset($_POST['agent_id'])) {
795
+ $chat_id = intval($_POST['cid']);
796
+ $agent_id = intval($_POST['agent_id']);
797
+ if (wplc_mrg_admin_transfer_to_agent($chat_id, $agent_id, false)) {
798
+ echo "true";
799
+ } else {
800
+ echo "false";
801
+ }
802
+ }
803
+ exit();
804
+ }
805
+
806
+ if ($_POST['action'] == "wplc_admin_transfer_to_department") {
807
+ if (isset($_POST['cid']) && isset($_POST['dep_id'])) {
808
+ $chat_id = intval($_POST['cid']);
809
+ $dep_id = intval($_POST['dep_id']);
810
+ if (wplc_mrg_admin_transfer_to_department($chat_id, $dep_id)) {
811
+ echo "true";
812
+ } else {
813
+ echo "false";
814
+ }
815
+ }
816
+ exit();
817
+ }
818
+ }
819
+ }
 
 
 
 
 
 
 
 
 
 
js/media.js CHANGED
@@ -92,22 +92,21 @@ jQuery(function($){
92
 
93
  $("#wplc_btn_remove_pic").click(function() {
94
  $("#wplc_pic_area").empty();
95
- $("#wplc_upload_pic").val("");
96
  });
97
  $("#wplc_btn_remove_logo").click(function() {
98
  $("#wplc_logo_area").empty();
99
- $("#wplc_upload_logo").val("");
100
  });
101
- $("#wplc_btn_remove_icon").click(function() {
102
- $("#wplc_icon_area").empty();
103
- $("#wplc_upload_icon").val("");
104
- });
105
-
106
-
107
  $("#wplc_btn_select_default_icon").click(function() {
108
  $("#wplc_default_chat_icons").slideToggle();
109
  });
110
 
 
 
 
 
 
111
  $(".wplc_default_chat_icon_selector").click(function() {
112
  var image_url = $(this).attr("src");
113
  $('#wplc_upload_icon').val(btoa(image_url));
92
 
93
  $("#wplc_btn_remove_pic").click(function() {
94
  $("#wplc_pic_area").empty();
95
+ $("#wplc_upload_pic").val("remove");
96
  });
97
  $("#wplc_btn_remove_logo").click(function() {
98
  $("#wplc_logo_area").empty();
99
+ $("#wplc_upload_logo").val("remove");
100
  });
 
 
 
 
 
 
101
  $("#wplc_btn_select_default_icon").click(function() {
102
  $("#wplc_default_chat_icons").slideToggle();
103
  });
104
 
105
+ $("#wplc_btn_select_default_pic").click(function() {
106
+ $('#wplc_upload_pic').val(btoa($("#wplc_pic_area").attr('default')));
107
+ $("#wplc_pic_area").html("<img src=\""+$("#wplc_pic_area").attr('default')+"\" width='50px'/>");
108
+ });
109
+
110
  $(".wplc_default_chat_icon_selector").click(function() {
111
  var image_url = $(this).attr("src");
112
  $('#wplc_upload_icon').val(btoa(image_url));
js/wplc_agent_node.js CHANGED
@@ -2280,7 +2280,7 @@ function nc_return_location_details(data) {
2280
  return "<img src='" + wplc_baseurl + "images/flags/" + location_info.code + ".png' alt='" + country_name + "' title='" + country_name + "' />";
2281
  }
2282
  }
2283
- catch {
2284
  // invalid data
2285
  }
2286
  }
@@ -2873,14 +2873,12 @@ tcx_delegates = function() {
2873
  }
2874
  });
2875
 
2876
-
2877
  socket.on('agent connected', function(data) {
2878
  var t_c_aid = data.aid;
2879
  var t_c_sid = data.socketid;
2880
  jQuery(".online_agent_" + t_c_aid).attr('socket', t_c_sid);
2881
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').removeClass('offline');
2882
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').addClass('online');
2883
-
2884
  jQuery.event.trigger({ type: "tcx_agent_connected", ndata: data });
2885
  });
2886
 
@@ -2890,7 +2888,6 @@ tcx_delegates = function() {
2890
  jQuery(".online_agent_" + t_c_aid).attr('socket', null);
2891
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').removeClass('online');
2892
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').addClass('offline');
2893
-
2894
  jQuery.event.trigger({ type: "tcx_agent_disconnected", ndata: data });
2895
  });
2896
 
2280
  return "<img src='" + wplc_baseurl + "images/flags/" + location_info.code + ".png' alt='" + country_name + "' title='" + country_name + "' />";
2281
  }
2282
  }
2283
+ catch (e) {
2284
  // invalid data
2285
  }
2286
  }
2873
  }
2874
  });
2875
 
 
2876
  socket.on('agent connected', function(data) {
2877
  var t_c_aid = data.aid;
2878
  var t_c_sid = data.socketid;
2879
  jQuery(".online_agent_" + t_c_aid).attr('socket', t_c_sid);
2880
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').removeClass('offline');
2881
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').addClass('online');
 
2882
  jQuery.event.trigger({ type: "tcx_agent_connected", ndata: data });
2883
  });
2884
 
2888
  jQuery(".online_agent_" + t_c_aid).attr('socket', null);
2889
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').removeClass('online');
2890
  jQuery(".online_agent_" + t_c_aid + ' .online_offline').addClass('offline');
 
2891
  jQuery.event.trigger({ type: "tcx_agent_disconnected", ndata: data });
2892
  });
2893
 
js/wplc_choose.js CHANGED
@@ -5,23 +5,81 @@ jQuery(function() {
5
  wplc_choose_delegate();
6
  });
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  jQuery(document).on("tcx_dom_ready", function(e) {
9
  wplc_choose_delegate();
10
 
11
- /**
12
- * New agent connected
13
- */
14
- jQuery(document).on("tcx_agent_connected", function(e) {
15
- wplc_ma_update_admin_bar(1, "event one"); //Add one agent
16
- });
17
-
18
- /**
19
- * New agent disconnected
20
- */
21
- jQuery(document).on("tcx_agent_disconnected", function(e) {
22
- if(typeof e.ndata.chatid !== 'undefined'){ return; }
23
- wplc_ma_update_admin_bar(-1, "event off"); //remove one agent
24
- });
25
  });
26
 
27
  function wplc_choose_delegate() {
@@ -40,19 +98,6 @@ function wplc_choose_delegate() {
40
  jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.not_accepting_chats);
41
  }
42
 
43
- //Transient
44
- function wplc_ma_update_agent_transient(data) {
45
- jQuery.post(ajaxurl, data, function(response) {
46
- if (response) {
47
- if (!config.wplc_use_node_server) {
48
- window.location.reload();
49
- } else {
50
- jQuery.event.trigger({type: "wplc_switchery_changed",response:response, ndata:data});
51
- }
52
- }
53
- });
54
- }
55
-
56
  /* Make sure switchery has been loaded on this page */
57
  if (typeof Switchery !== 'undefined') {
58
  var wplc_switchery_element = document.querySelector('.wplc_switchery');
@@ -67,26 +112,9 @@ function wplc_choose_delegate() {
67
  setTimeout(function() {wplc_switchery_init.enable();},3000);
68
  var wplc_accepting_chats = jQuery(this).attr('checked');
69
  if (wplc_accepting_chats === 'checked') {
70
- connection_lost_type = '';
71
- jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.accepting_status);
72
- var data = {
73
- action: 'wplc_choose_accepting',
74
- security: wplc_admin_strings.nonce,
75
- user_id: wplc_admin_strings.user_id
76
- };
77
- wplc_ma_update_agent_transient(data);
78
- wplc_ma_update_admin_bar(1, "click on"); //Add one agent
79
  } else {
80
- jQuery.event.trigger({type: "wplc_end_all_open_chats"});
81
- jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.not_accepting_status);
82
- connection_lost_type = 'offline_status';
83
- var data = {
84
- action: 'wplc_choose_not_accepting',
85
- security: wplc_admin_strings.nonce,
86
- user_id: wplc_admin_strings.user_id
87
- };
88
- wplc_ma_update_agent_transient(data);
89
- wplc_ma_update_admin_bar(-1, "click off"); //remove one agent
90
  }
91
  };
92
 
@@ -94,33 +122,60 @@ function wplc_choose_delegate() {
94
  }
95
  }
96
 
97
- //Parse the current value
98
- function wplc_ma_update_admin_bar(amount, where){
99
- wplc_online_agent_count = wplc_ma_parse_active_count_from_container();
100
- wplc_online_agent_count += amount; //we can add a negative value to remove
101
-
102
- if(wplc_online_agent_count < 0){
103
- wplc_online_agent_count = 0; //Force to lowest possible
 
 
104
  }
 
 
105
 
106
- if(wplc_online_agent_count > 0){
107
- //Online
108
- jQuery("#wplc_ma_online_agents_circle").removeClass("wplc_red_circle");
109
- if(!jQuery("#wplc_ma_online_agents_circle").hasClass("wplc_green_circle")){
110
- jQuery("#wplc_ma_online_agents_circle").addClass("wplc_green_circle");
111
- }
112
- } else {
113
- //Offline
114
- jQuery("#wplc_ma_online_agents_circle").removeClass("wplc_green_circle");
115
- if(!jQuery("#wplc_ma_online_agents_circle").hasClass("wplc_red_circle")){
116
- jQuery("#wplc_ma_online_agents_circle").addClass("wplc_red_circle");
117
- }
118
- }
119
 
120
- jQuery("#wplc_ma_online_agents_count").text(wplc_online_agent_count);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  //Get the value currently stored in the admin bar
124
  function wplc_ma_parse_active_count_from_container(){
125
  return parseInt(jQuery("#wplc_ma_online_agents_count").text());
126
- }
 
 
5
  wplc_choose_delegate();
6
  });
7
 
8
+ function wplc_update_agent_status(isOnline) {
9
+ if (isOnline) {
10
+ jQuery('#wplc_online_topbar_switch').removeClass('wplc_online_topbar_switch_offline');
11
+ jQuery('#wplc_online_topbar_switch').addClass('wplc_online_topbar_switch_online');
12
+ jQuery('#wplc_ma_online_agent_text').text(wplc_choose_admin_strings.accepting_chats);
13
+ jQuery('#wplc_online_topbar_switch').attr('checked','true');
14
+ } else {
15
+ jQuery('#wplc_online_topbar_switch').removeClass('wplc_online_topbar_switch_online');
16
+ jQuery('#wplc_online_topbar_switch').addClass('wplc_online_topbar_switch_offline');
17
+ jQuery('#wplc_ma_online_agent_text').text(wplc_choose_admin_strings.not_accepting_chats);
18
+ jQuery('#wplc_online_topbar_switch').removeAttr('checked');
19
+ }
20
+ }
21
+
22
+ jQuery(document).ready(function() {
23
+ jQuery('#wplc_online_topbar_switch').on('click',function(e) {
24
+ jQuery('#wplc_online_topbar_switch').attr('disabled', true);
25
+ setTimeout(function() {jQuery('#wplc_online_topbar_switch').removeAttr('disabled');}, 2000);
26
+ if (jQuery('#wplc_online_topbar_switch').attr('checked')) {
27
+ if (jQuery('#wplc_agent_status').length) {
28
+ jQuery('#wplc_agent_status').click();
29
+ } else {
30
+ wplc_set_agent_online();
31
+ }
32
+ } else {
33
+ if (jQuery('#wplc_agent_status').length) {
34
+ jQuery('#wplc_agent_status').click();
35
+ } else {
36
+ wplc_set_agent_offline();
37
+ }
38
+ }
39
+ return true;
40
+ });
41
+
42
+ jQuery(document).on("wplc_agent_online_changed", function(e) {
43
+ if (typeof e.response !== "undefined") {
44
+ var reply = JSON.parse(e.response);
45
+ if (!!reply && reply.agents) {
46
+ jQuery("#wplc_ma_online_agents_label").text(wplc_choose_admin_strings.agent_online_plural);
47
+ if (reply.agents.length>0) { // at least one agent online
48
+ // agent count
49
+ jQuery("#wplc_ma_online_agents_circle").removeClass("wplc_red_circle");
50
+ jQuery("#wplc_ma_online_agents_circle").addClass("wplc_green_circle");
51
+ if (reply.agents.length==1) {
52
+ jQuery("#wplc_ma_online_agents_label").text(wplc_choose_admin_strings.agent_online_singular);
53
+ }
54
+ } else { // no agents online
55
+ // agent count
56
+ jQuery("#wplc_ma_online_agents_circle").removeClass("wplc_green_circle");
57
+ jQuery("#wplc_ma_online_agents_circle").addClass("wplc_red_circle");
58
+ }
59
+ jQuery("#wplc_ma_online_agents_count").text(reply.agents.length);
60
+ }
61
+ // todo: update dropdown agent list in admin menu
62
+ }
63
+
64
+ });
65
+
66
+ jQuery(document).on("wplc_switchery_changed", function(e) {
67
+ jQuery.event.trigger({type: "wplc_agent_online_changed", response: e.response, ndata:e.ndata});
68
+ });
69
+
70
+ jQuery(document).on("tcx_agent_connected", function(e) {
71
+ wplc_ma_update_admin_bar();
72
+ });
73
+
74
+ jQuery(document).on("tcx_agent_disconnected", function(e) {
75
+ wplc_ma_update_admin_bar();
76
+ });
77
+
78
+ });
79
+
80
  jQuery(document).on("tcx_dom_ready", function(e) {
81
  wplc_choose_delegate();
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  });
84
 
85
  function wplc_choose_delegate() {
98
  jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.not_accepting_chats);
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  /* Make sure switchery has been loaded on this page */
102
  if (typeof Switchery !== 'undefined') {
103
  var wplc_switchery_element = document.querySelector('.wplc_switchery');
112
  setTimeout(function() {wplc_switchery_init.enable();},3000);
113
  var wplc_accepting_chats = jQuery(this).attr('checked');
114
  if (wplc_accepting_chats === 'checked') {
115
+ wplc_set_agent_online();
 
 
 
 
 
 
 
 
116
  } else {
117
+ wplc_set_agent_offline();
 
 
 
 
 
 
 
 
 
118
  }
119
  };
120
 
122
  }
123
  }
124
 
125
+ //Transient
126
+ function wplc_ma_update_agent_transient(data) {
127
+ jQuery.post(ajaxurl, data, function(response) {
128
+ if (response) {
129
+ if (!config.wplc_use_node_server) {
130
+ window.location.reload();
131
+ } else {
132
+ jQuery.event.trigger({type: "wplc_switchery_changed", response:response, ndata:data});
133
+ }
134
  }
135
+ });
136
+ }
137
 
138
+ function wplc_set_agent_online() {
139
+ connection_lost_type = '';
140
+ jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.accepting_status);
141
+ var data = {
142
+ action: 'wplc_choose_accepting',
143
+ security: wplc_admin_strings.nonce,
144
+ user_id: wplc_admin_strings.user_id
145
+ };
146
+ wplc_update_agent_status(true);
147
+ wplc_ma_update_agent_transient(data);
148
+ }
 
 
149
 
150
+ function wplc_set_agent_offline() {
151
+ jQuery.event.trigger({type: "wplc_end_all_open_chats"});
152
+ jQuery("#wplc_agent_status_text").html(wplc_choose_admin_strings.not_accepting_status);
153
+ connection_lost_type = 'offline_status';
154
+ var data = {
155
+ action: 'wplc_choose_not_accepting',
156
+ security: wplc_admin_strings.nonce,
157
+ user_id: wplc_admin_strings.user_id
158
+ };
159
+ wplc_update_agent_status(false);
160
+ wplc_ma_update_agent_transient(data);
161
+ }
162
+
163
+ function wplc_ma_update_admin_bar() {
164
+ var data = {
165
+ action: 'wplc_agent_list',
166
+ security: wplc_admin_strings.nonce,
167
+ user_id: wplc_admin_strings.user_id
168
+ };
169
+ jQuery.post(ajaxurl, data, function(response) {
170
+ if (response) {
171
+ jQuery.event.trigger({type: "wplc_agent_online_changed", response: response, ndata:data});
172
+ }
173
+ });
174
  }
175
 
176
  //Get the value currently stored in the admin bar
177
  function wplc_ma_parse_active_count_from_container(){
178
  return parseInt(jQuery("#wplc_ma_online_agents_count").text());
179
+ }
180
+
181
+ setInterval(function() {wplc_ma_update_admin_bar();}, 30000); // force update agent count - for offline agents
js/wplc_gutenberg.js CHANGED
@@ -164,7 +164,7 @@ jQuery(function($){
164
  templates['template_default'] = '<!-- Default Template - Dark -->\n<div class="wplc_block">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
165
  templates['template_default_tooltip'] = '<!-- Default - Tooltip -->\n<!-- Hover over the block to see the tooltip -->\n<div class="wplc_block">\n\t<span class="wplc_block_tooltip">Want to chat?</span>\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
166
  templates['template_default_light'] = '<!-- Default - Light Template -->\n<div class="wplc_block light">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
167
- templates['template_tooltip'] = '<!-- Cricle - Tooltip Template -->\n<!-- Hover over the block to see the tooltip -->\n<div class="wplc_block circle">\n\t<span class="wplc_block_tooltip">Chat with us!</span>\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n</div>';
168
  templates['template_circle'] = '<!-- Circle Template -->\n<div class="wplc_block circle">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n</div>';
169
  templates['template_chat_bubble'] = '<!-- Chat Bubble Template -->\n<div class="wplc_block chat_bubble">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n</div>';
170
  templates['template_circle_rotate'] = '<!-- Circle - Rotating Template -->\n<!-- Hover over the icon to see it rotate -->\n<div class="wplc_block circle rotate">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
164
  templates['template_default'] = '<!-- Default Template - Dark -->\n<div class="wplc_block">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
165
  templates['template_default_tooltip'] = '<!-- Default - Tooltip -->\n<!-- Hover over the block to see the tooltip -->\n<div class="wplc_block">\n\t<span class="wplc_block_tooltip">Want to chat?</span>\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
166
  templates['template_default_light'] = '<!-- Default - Light Template -->\n<div class="wplc_block light">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
167
+ templates['template_tooltip'] = '<!-- Circle - Tooltip Template -->\n<!-- Hover over the block to see the tooltip -->\n<div class="wplc_block circle">\n\t<span class="wplc_block_tooltip">Chat with us!</span>\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n</div>';
168
  templates['template_circle'] = '<!-- Circle Template -->\n<div class="wplc_block circle">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n</div>';
169
  templates['template_chat_bubble'] = '<!-- Chat Bubble Template -->\n<div class="wplc_block chat_bubble">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_text">{wplc_text}</span>\n</div>';
170
  templates['template_circle_rotate'] = '<!-- Circle - Rotating Template -->\n<!-- Hover over the icon to see it rotate -->\n<div class="wplc_block circle rotate">\n\t<span class="wplc_block_logo">{wplc_logo}</span>\n\t<span class="wplc_block_icon">{wplc_icon}</span>\n</div>';
js/wplc_ma_transient.js CHANGED
@@ -12,6 +12,7 @@
12
  user_id: wplc_admin_strings.user_id
13
  };
14
  jQuery.post(ajaxurl, data, function(response) {
 
15
  });
16
  }
17
  });
12
  user_id: wplc_admin_strings.user_id
13
  };
14
  jQuery.post(ajaxurl, data, function(response) {
15
+ jQuery.event.trigger({type: "wplc_agent_online_changed", response: response, ndata:data});
16
  });
17
  }
18
  });
js/wplc_server.js CHANGED
@@ -341,52 +341,6 @@ function wplc_rest_api(type, wplc_send_data, wplc_send_timeout, next) {
341
  }
342
  }
343
 
344
- function wplc_socket_async_storage_handler(wplc_send_url, wplc_send_data, wplc_send_timeout){
345
- var wplc_node_ajax_action = "wplc_node_async_storage_ajax";
346
- //Send the data to the Async
347
- if(!!wplc_restapi_enabled.value && typeof wplc_restapi_endpoint !== "undefined") {
348
- //REST API
349
- wplc_send_url = wplc_restapi_endpoint + "/async_storage";
350
- } else {
351
- //Ajax
352
- }
353
-
354
- var prepared_data = {
355
- action : wplc_node_ajax_action,
356
- relay_action : wplc_send_data.action,
357
- chat_id : wplc_send_data.cid,
358
- security : wplc_send_data.security,
359
- messages : JSON.stringify(wplc_node_async_array),
360
- wplc_extra_data:document.wplc_extra_data
361
- };
362
-
363
- if(typeof tcx_api_key !== "undefined"){
364
- prepared_data.server_token = tcx_api_key;
365
- }
366
-
367
- /*
368
- wplc_node_async_array = new Array(); //Clearing the storage array before the next data can be sent through
369
- if(typeof Cookies !== "undefined" && typeof Cookies === "function"){
370
- Cookies.remove('wplc_server_async_storage'); //Clear the cookies now so that we don't do this again.
371
- }
372
- */
373
- jQuery.ajax({
374
- url : wplc_send_url,
375
- data : prepared_data,
376
- type : "POST",
377
- timeout : wplc_send_timeout,
378
- success : function(response){
379
- wplc_server_log("ASYNC STORAGE = SUCCESS");
380
- },
381
- error : function(error, exception){
382
- wplc_server_log("ASYNC STORAGE = FAIL");
383
- },
384
- complete : function(response){
385
-
386
- }
387
- });
388
- }
389
-
390
  function wplc_json_validator(str) {
391
  try {
392
  JSON.parse(str);
341
  }
342
  }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  function wplc_json_validator(str) {
345
  try {
346
  JSON.parse(str);
js/wplc_u_admin_events.js CHANGED
@@ -542,7 +542,7 @@ jQuery(document).on("tcx_dom_ready", function(e) {
542
  jQuery(document).on("wplc_switchery_changed", function(e) {
543
  if (typeof e.ndata !== "undefined" && typeof e.ndata.action !== "undefined" && e.ndata.action === "wplc_choose_not_accepting") {
544
  /* drop the connection */
545
- if (socket.connected) {
546
  socket.disconnect();
547
  }
548
  } else if (e.ndata.action === "wplc_choose_accepting") {
542
  jQuery(document).on("wplc_switchery_changed", function(e) {
543
  if (typeof e.ndata !== "undefined" && typeof e.ndata.action !== "undefined" && e.ndata.action === "wplc_choose_not_accepting") {
544
  /* drop the connection */
545
+ if (!!socket && socket.connected) {
546
  socket.disconnect();
547
  }
548
  } else if (e.ndata.action === "wplc_choose_accepting") {
js/wplc_u_pro.js CHANGED
@@ -134,7 +134,7 @@ jQuery(function() {
134
  var height = jQuery('#wplc_chatbox')[0].scrollHeight;
135
  jQuery('#wplc_chatbox').scrollTop(height);
136
  if (!!wplc_enable_ding.value) {
137
- new Audio(wplc_plugin_url + '/wp-live-chat-support/includes/sounds/general/ding.mp3').play()
138
  }
139
 
140
  }
134
  var height = jQuery('#wplc_chatbox')[0].scrollHeight;
135
  jQuery('#wplc_chatbox').scrollTop(height);
136
  if (!!wplc_enable_ding.value) {
137
+ new Audio(wplc_plugin_url + 'wp-live-chat-support/includes/sounds/general/ding.mp3').play()
138
  }
139
 
140
  }
modules/api/agent/wplc-api-functions.php CHANGED
@@ -1,8 +1,8 @@
1
- <?php
2
  /* Handles all functions related to the WP Live Chat Support API */
3
 
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
  }
7
 
8
 
@@ -13,64 +13,74 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  * - Chat ID
14
  * - Agent ID
15
  */
16
- function wplc_api_accept_chat(WP_REST_Request $request){
17
-
18
- $return_array = array();
19
- if(isset($request)){
20
- if(isset($request['token'])){
21
- $check_token = get_option('wplc_api_secret_token');
22
- if($check_token !== false && $request['token'] === $check_token){
23
- if(isset($request['chat_id'])){
24
- if(isset($request['agent_id'])){
25
-
26
- $cid = wplc_return_chat_id_by_rel($request['chat_id']);
27
- if(wplc_change_chat_status($cid, 3, intval($request['agent_id']))){
28
-
29
-
30
- do_action("wplc_hook_update_agent_id", sanitize_text_field($request['cid']) ,intval($request['agent_id']));
31
-
32
- $return_array['response'] = "Chat accepted successfully";
33
- $return_array['code'] = "200";
34
- $return_array['data'] = array("chat_id" => intval($request['chat_id']),
35
- "agent_id" => intval($request['agent_id']));
36
- } else {
37
- $return_array['response'] = "Status could not be changed";
38
- $return_array['code'] = "404";
39
- }
40
- } else {
41
- $return_array['response'] = "No 'agent_id' found";
42
- $return_array['code'] = "401";
43
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
44
- "chat_id" => "Chat ID",
45
- "agent_id" => "Agent ID");
46
- }
47
- } else {
48
- $return_array['response'] = "No 'chat_id' found";
49
- $return_array['code'] = "401";
50
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
51
- "chat_id" => "Chat ID",
52
- "agent_id" => "Agent ID");
53
- }
54
- } else {
55
- $return_array['response'] = "Secret token is invalid";
56
- $return_array['code'] = "401";
57
- }
58
- }else{
59
- $return_array['response'] = "No secret 'token' found";
60
- $return_array['code'] = "401";
61
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
62
- "chat_id" => "Chat ID",
63
- "agent_id" => "Agent ID");
64
- }
65
- }else{
66
- $return_array['response'] = "No request data found";
67
- $return_array['code'] = "400";
68
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
69
- "chat_id" => "Chat ID",
70
- "agent_id" => "Agent ID");
71
- }
72
-
73
- return $return_array;
 
 
 
 
 
 
 
 
 
 
74
  }
75
 
76
  /*
@@ -80,68 +90,78 @@ function wplc_api_accept_chat(WP_REST_Request $request){
80
  * - Chat ID
81
  * - Agent ID
82
  */
83
- function wplc_api_agent_end_chat(WP_REST_Request $request){
84
-
85
- $return_array = array();
86
- if(isset($request)){
87
- if(isset($request['token'])){
88
- $check_token = get_option('wplc_api_secret_token');
89
- if($check_token !== false && $request['token'] === $check_token){
90
- if(isset($request['chat_id'])){
91
- if(isset($request['agent_id'])){
92
-
93
- $cid = $request['chat_id'];
94
- if( ! filter_var($request['chat_id'], FILTER_VALIDATE_INT) ) {
95
- /* We need to identify if this CID is a node CID, and if so, return the WP CID */
96
- $cid = wplc_return_chat_id_by_rel($cid);
97
- }
98
-
99
- if(wplc_change_chat_status($cid, 1, intval($request['agent_id']))){
100
-
101
- do_action('wplc_send_transcript_hook', $cid);
102
-
103
- $return_array['response'] = "Chat ended successfully";
104
- $return_array['code'] = "200";
105
- $return_array['data'] = array("chat_id" => $cid,
106
- "agent_id" => intval($request['agent_id']));
107
- } else {
108
- $return_array['response'] = "Status could not be changed";
109
- $return_array['code'] = "404";
110
- }
111
- } else {
112
- $return_array['response'] = "No 'agent_id' found";
113
- $return_array['code'] = "401";
114
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
115
- "chat_id" => "Chat ID",
116
- "agent_id" => "Agent ID");
117
- }
118
- } else {
119
- $return_array['response'] = "No 'chat_id' found";
120
- $return_array['code'] = "401";
121
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
122
- "chat_id" => "Chat ID",
123
- "agent_id" => "Agent ID");
124
- }
125
- } else {
126
- $return_array['response'] = "Secret token is invalid";
127
- $return_array['code'] = "401";
128
- }
129
- }else{
130
- $return_array['response'] = "No secret 'token' found";
131
- $return_array['code'] = "401";
132
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
133
- "chat_id" => "Chat ID",
134
- "agent_id" => "Agent ID");
135
- }
136
- }else{
137
- $return_array['response'] = "No request data found";
138
- $return_array['code'] = "400";
139
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
140
- "chat_id" => "Chat ID",
141
- "agent_id" => "Agent ID");
142
- }
143
-
144
- return $return_array;
 
 
 
 
 
 
 
 
 
 
145
  }
146
 
147
 
@@ -153,79 +173,86 @@ function wplc_api_agent_end_chat(WP_REST_Request $request){
153
  * - Chat ID
154
  * - Message
155
  */
156
- function wplc_api_agent_send_message(WP_REST_Request $request){
157
-
158
- $return_array = array();
159
- if(isset($request)){
160
- if(isset($request['server_token'])){
161
- $check_token = get_option('wplc_api_secret_token');
162
- if($check_token !== false && $request['server_token'] === $check_token){
163
- if(isset($request['chat_id'])){
164
- if(isset($request['message'])){
165
- if(isset($request['relay_action'])){
166
-
167
- $chat_id = sanitize_text_field($request['chat_id']);
168
- $message = $request['message'];
169
- $action = $request['relay_action'];
170
-
171
- if (!empty($request['msg_id'])) {
172
- $other = new stdClass();
173
- $other->msgID = $request['msg_id'];
174
- } else {
175
- $other = false;
176
- }
177
-
178
- if ($action == "wplc_admin_send_msg"){
179
- wplc_record_chat_msg("2", $chat_id, $message, true, sanitize_text_field( $request['agent_id'] ), $other);
180
- wplc_update_active_timestamp($chat_id);
181
-
182
- $return_array['response'] = "Message sent successfully";
183
- $return_array['code'] = "200";
184
- $return_array['data'] = array("chat_id" => sanitize_text_field($request['chat_id']),
185
- "agent_id" => intval($request['agent_id']));
186
-
187
- do_action("wplc_new_user_message_after_record_hook", $chat_id, $message);
188
- }
189
-
190
-
191
-
192
- } else {
193
- $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
194
- }
195
- } else {
196
- $return_array['response'] = "No 'message' found";
197
- $return_array['code'] = "401";
198
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
199
- "chat_id" => "Chat ID",
200
- "message" => "Message");
201
- }
202
- } else {
203
- $return_array['response'] = "No 'chat_id' found";
204
- $return_array['code'] = "401";
205
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
206
- "chat_id" => "Chat ID",
207
- "message" => "Message");
208
- }
209
- } else {
210
- $return_array['response'] = "Secret server_token is invalid";
211
- $return_array['code'] = "401";
212
- }
213
- }else{
214
- $return_array['response'] = "No secret 'server_token' found";
215
- $return_array['code'] = "401";
216
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
217
- "chat_id" => "Chat ID",
218
- "message" => "Message");
219
- }
220
- }else{
221
- $return_array['response'] = "No request data found";
222
- $return_array['code'] = "400";
223
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
224
- "chat_id" => "Chat ID",
225
- "message" => "Message");
226
- }
227
-
228
- return $return_array;
 
 
 
 
 
 
 
229
  }
230
 
231
 
@@ -239,180 +266,181 @@ function wplc_api_agent_send_message(WP_REST_Request $request){
239
  * - Limit (Defaults to 50/Max Limit of 50)
240
  * - Offset (Defaults to 0)
241
  */
242
- function wplc_api_agent_get_messages(WP_REST_Request $request){
243
-
244
- $return_array = array();
245
- if(isset($request)){
246
- if(isset($request['token'])){
247
- $check_token = get_option('wplc_api_secret_token');
248
- if($check_token !== false && $request['token'] === $check_token){
249
- if(isset($request['chat_id'])){
250
- $limit = 50;
251
- $offset = 0;
252
- if(isset($request['limit'])){
253
- $limit = intval($request['limit']);
254
- }
255
- if(isset($request['offset'])){
256
- $offset = intval($request['offset']);
257
- }
258
-
259
- if ( isset( $request['received_via'] ) ) {
260
- $received_via = sanitize_text_field( $request['received_via'] );
261
- } else {
262
- $received_via = 'u';
263
- }
264
-
265
- $message_data = wplc_api_return_messages($request['chat_id'], $limit, $offset, $received_via);
266
-
267
- if($message_data){
268
- $return_array['response'] = "Message data returned";
269
- $return_array['code'] = "200";
270
- $return_array['data'] = array("messages" => $message_data);
271
- } else {
272
- $return_array['response'] = "Messages not found";
273
- $return_array['code'] = "404";
274
- $return_array['data'] = array("chat_id" => intval($request['chat_id']));
275
- }
276
- } else {
277
- $return_array['response'] = "No 'chat_id' found";
278
- $return_array['code'] = "401";
279
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
280
- "chat_id" => "Chat ID");
281
- }
282
- } else {
283
- $return_array['response'] = "Secret token is invalid";
284
- $return_array['code'] = "401";
285
- }
286
- }else{
287
- $return_array['response'] = "No secret 'token' found";
288
- $return_array['code'] = "401";
289
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
290
- "chat_id" => "Chat ID");
291
- }
292
- }else{
293
- $return_array['response'] = "No request data found";
294
- $return_array['code'] = "400";
295
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN",
296
- "chat_id" => "Chat ID");
297
- }
298
-
299
- return $return_array;
 
 
 
 
 
 
300
  }
301
 
302
 
303
  /*
304
  * Records an admin message via the API
305
  */
306
- function wplc_api_agent_record_admin_message($cid, $msg){
307
-
308
- global $wpdb;
309
- global $wplc_tblname_msgs;
310
-
311
- $fromname = apply_filters("wplc_filter_admin_name","Admin");
312
- $orig = '1';
313
-
314
- $msg = apply_filters("wplc_filter_message_control",$msg);
315
-
316
- $wpdb->insert(
317
- $wplc_tblname_msgs,
318
- array(
319
- 'chat_sess_id' => $cid,
320
- 'timestamp' => current_time('mysql'),
321
- 'msgfrom' => $fromname,
322
- 'msg' => $msg,
323
- 'status' => 0,
324
- 'originates' => $orig
325
- ),
326
- array(
327
- '%s',
328
- '%s',
329
- '%s',
330
- '%s',
331
- '%d',
332
- '%s'
333
- )
334
- );
335
-
336
- wplc_update_active_timestamp(sanitize_text_field($cid));
337
- wplc_change_chat_status(sanitize_text_field($cid),3);
338
-
339
- return true;
340
  }
341
 
342
  /*
343
  * Returns messages from server
344
  */
345
- function wplc_api_agent_return_messages($cid, $limit, $offset, $received_via = 'u'){
 
 
 
 
 
 
 
 
 
 
346
 
347
- $cid = wplc_return_chat_id_by_rel($cid);
 
 
348
 
349
- $messages = wplc_return_chat_messages( $cid, false, true, false, false, 'array', false );
350
 
351
- if ($received_via === 'u') {
352
- wplc_mark_as_read_user_chat_messages( $cid );
353
- } else {
354
- wplc_mark_as_read_agent_chat_messages( $cid, $received_via );
355
- }
356
- return $messages;
357
 
 
 
 
 
 
 
 
358
 
359
- }
 
 
 
 
 
360
 
361
 
362
- function wplc_api_agent_return_sessions() {
363
- global $wpdb;
364
- global $wplc_tblname_chats;
365
-
366
- $results = $wpdb->get_results("SELECT * FROM $wplc_tblname_chats WHERE `status` = 3 OR `status` = 2 OR `status` = 10 OR `status` = 5 or `status` = 8 or `status` = 9 ORDER BY `timestamp` ASC");
367
-
368
- $session_array = array();
369
-
370
- if ($results) {
371
- foreach ($results as $result) {
372
- $ip_info = maybe_unserialize($result->ip);
373
- $user_ip = $ip_info['ip'];
374
- if($user_ip == ""){
375
- $user_ip = __('IP Address not recorded', 'wp-live-chat-support');
376
- }
377
 
378
- $browser = 'Unknown';
379
- $browser_image = '';
380
- if(!empty($ip_info['user_agent'])){
381
- $browser = wplc_return_browser_string($ip_info['user_agent']);
382
- $browser_image = wplc_return_browser_image($browser,"16");
383
- }
384
-
385
-
386
- $session_array[$result->id] = array();
387
-
388
- $session_array[$result->id]['name'] = $result->name;
389
- $session_array[$result->id]['email'] = $result->email;
390
-
391
- $session_array[$result->id]['status'] = $result->status;
392
- $session_array[$result->id]['timestamp'] = wplc_time_ago($result->timestamp);
393
-
394
- if ((current_time('timestamp') - strtotime($result->timestamp)) < 3600) {
395
- $session_array[$result->id]['type'] = __("New",'wp-live-chat-support');
396
- } else {
397
- $session_array[$result->id]['type'] = __("Returning",'wp-live-chat-support');
398
- }
399
-
400
- $session_array[$result->id]['image'] = "//www.gravatar.com/avatar/".md5($result->email)."?s=30&d=mm";
401
- $session_array[$result->id]['data']['browsing'] = $result->url;
402
- $path = parse_url($result->url, PHP_URL_PATH);
403
-
404
- if (strlen($path) > 20) {
405
- $session_array[$result->id]['data']['browsing_nice_url'] = substr($path,0,20).'...';
406
- } else {
407
- $session_array[$result->id]['data']['browsing_nice_url'] = $path;
408
- }
409
-
410
- $session_array[$result->id]['data']['browser'] = WPLC_PLUGIN_URL . "images/$browser_image";
411
- $session_array[$result->id]['data']['ip'] = $user_ip;
412
- }
413
  }
414
-
415
- return $session_array;
 
416
  }
417
 
418
 
@@ -425,295 +453,285 @@ function wplc_api_agent_return_sessions() {
425
  /*
426
  * Upload end point
427
  */
428
- function wplc_api_remote_upload(WP_REST_Request $request){
429
-
430
- $return_array = array();
431
- $return_array['response'] = 'false';
432
-
433
- $return_array = apply_filters("wplc_api_remote_upload_filter", $return_array, $request);
434
-
435
- return $return_array;
436
  }
437
 
438
  /*
439
  * Rest Permission check for restricted end points
440
  */
441
- function wplc_api_agent_permission_check(){
442
- if( is_user_logged_in() && current_user_can( 'wplc_ma_agent' ) ){
443
- return true;
444
- }else {
445
- return false;
446
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
 
449
- function wplc_agent_validate_agent_check(WP_REST_Request $request){
450
 
451
- $return_array = array();
452
- if(isset($request)){
453
- if(isset($request['agent_id'])){
454
- if( get_user_meta(intval($request['agent_id']), 'wplc_ma_agent', true) ){
455
- $return_array['response'] = "true";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  $return_array['code'] = "200";
 
 
 
 
 
 
 
457
  } else {
458
- $return_array['response'] = "false";
459
- $return_array['code'] = "200";
460
  }
461
- }else{
462
- $return_array['response'] = "No Agent ID found";
463
  $return_array['code'] = "401";
464
- $return_array['requirements'] = array("agent_id" => "Agent ID");
 
 
 
 
 
 
 
 
 
 
 
 
 
465
  }
466
- }else{
467
- $return_array['response'] = "No request data found";
468
- $return_array['code'] = "400";
469
- $return_array['requirements'] = array("agent_id" => "Agent ID");
 
 
 
 
 
 
 
 
470
  }
471
-
472
- return $return_array;
 
 
 
 
 
 
 
 
 
473
  }
474
 
475
 
476
- # PRO API FUNCTIONS
477
- function wplc_api_send_agent_message_mrg(WP_REST_Request $request){
478
-
479
- $return_array = array();
480
- if(isset($request)){
481
- if(isset($request['server_token'])){
482
- $check_token = get_option('wplc_api_secret_token');
483
- if($check_token !== false && $request['server_token'] === $check_token){
484
- if(isset($request['chat_id'])){
485
- if(isset($request['message'])){
486
- if(isset($request['relay_action'])){
487
-
488
- $chat_id = sanitize_text_field($request['chat_id']);
489
- $message = $request['message'];
490
- $action = $request['relay_action'];
491
-
492
- if (!empty($request['msg_id'])) {
493
- $other = new stdClass();
494
- $other->msgID = $request['msg_id'];
495
- } else {
496
- $other = false;
497
- }
498
-
499
- if ($action == "wplc_admin_send_msg"){
500
- $message = sanitize_text_field( $message );
501
- $ato = intval( $request['ato'] );
502
- if(isset($request['orig_override'])){
503
- wplc_api_record_agent_chat_msg_mrg(sanitize_text_field( $request['agent_id'] ), $chat_id, $message, true, $ato, $other, $request['orig_override']);
504
- } else {
505
- wplc_api_record_agent_chat_msg_mrg(sanitize_text_field( $request['agent_id'] ), $chat_id, $message, true, $ato, $other);
506
- }
507
- wplc_update_active_timestamp($chat_id);
508
-
509
- $return_array['response'] = "Message sent successfully";
510
- $return_array['code'] = "200";
511
- $return_array['data'] = array("chat_id" => intval($request['chat_id']),
512
- "agent_id" => intval($request['agent_id']));
513
-
514
- do_action("wplc_new_user_message_after_record_hook", $chat_id, $message);
515
- }
516
-
517
-
518
-
519
- } else {
520
- $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
521
- }
522
- } else {
523
- $return_array['response'] = "No 'message' found";
524
- $return_array['code'] = "401";
525
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
526
- "chat_id" => "Chat ID",
527
- "message" => "Message");
528
- }
529
- } else {
530
- $return_array['response'] = "No 'chat_id' found";
531
- $return_array['code'] = "401";
532
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
533
- "chat_id" => "Chat ID",
534
- "message" => "Message");
535
- }
536
- } else {
537
- $return_array['response'] = "Secret server_token is invalid";
538
- $return_array['code'] = "401";
539
- }
540
- }else{
541
- $return_array['response'] = "No secret 'server_token' found";
542
- $return_array['code'] = "401";
543
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
544
- "chat_id" => "Chat ID",
545
- "message" => "Message");
546
- }
547
- }else{
548
- $return_array['response'] = "No request data found";
549
- $return_array['code'] = "400";
550
- $return_array['requirements'] = array("server_token" => "YOUR_SECRET_TOKEN",
551
- "chat_id" => "Chat ID",
552
- "message" => "Message");
553
- }
554
-
555
- return $return_array;
556
- }
557
 
 
 
 
 
 
 
 
 
558
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
 
560
- function wplc_api_get_agent_unread_message_counts_mrg( WP_REST_Request $request ) {
561
-
562
- $return_array = array();
563
- if(isset($request)){
564
- if(isset($request['token'])){
565
- $check_token = get_option('wplc_api_secret_token');
566
- if($check_token !== false && $request['token'] === $check_token){
567
-
568
- $current_agent = intval( sanitize_text_field( $request['agent_id'] ) );
569
-
570
- /**
571
- * Get all agents
572
- * @var [type]
573
- */
574
- $user_array = get_users(array(
575
- 'meta_key' => 'wplc_ma_agent',
576
- ));
577
-
578
-
579
- $a_array = array();
580
- if ($user_array) {
581
- foreach ($user_array as $user) {
582
- $unread = wplc_return_unread_agent_messages_mrg( $current_agent, $user->ID );
583
- $a_array[$user->ID] = $unread;
584
-
585
- }
586
- }
587
- $return_array['response'] = "Unread count agents"; /* needs to be exactly this for the JS to fire correctly */
588
- $return_array['code'] = "200";
589
- $return_array['data'] = $a_array;
590
-
591
- } else {
592
- $return_array['response'] = "Secret token is invalid";
593
- $return_array['code'] = "401";
594
- }
595
- }else{
596
- $return_array['response'] = "No secret 'token' found";
597
- $return_array['code'] = "401";
598
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN");
599
- }
600
- }else{
601
- $return_array['response'] = "No request data found";
602
- $return_array['code'] = "400";
603
- $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN");
604
- }
605
-
606
- return $return_array;
607
  }
608
 
609
  function wplc_api_initiate_chat_mrg(WP_REST_REQUEST $request) {
610
  $wplc_settings = wplc_get_options();
611
- $return_array = array();
612
- if(isset($request)) {
613
- if(isset($request['security'])) {
614
- $check_token = get_option('wplc_api_secret_token');
615
- if($check_token !== false && $request['token'] === $check_token) {
616
-
617
- if(isset($request['rel']) || isset($request['cid'])) {
618
-
619
- if(isset($request['aid'])) {
620
-
621
- $aid = intval( $request['aid'] );
622
-
623
- if (isset($request['rel'])) {
624
- $cid = $request['rel'];
625
- } else {
626
- $cid = $request['cid'];
627
- }
628
-
629
-
630
- global $wplc_tblname_chats;
631
- global $wpdb;
632
- $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `rel` = %s OR `id` = %s LIMIT 1", $cid, $cid));
633
- if (!$results) {
634
- /* it doesnt exist, lets put it in the table */
635
-
636
- $wpdb->insert(
637
- $wplc_tblname_chats,
638
- array(
639
- 'status' => 3,
640
- 'timestamp' => current_time('mysql'),
641
- 'name' => $wplc_settings['wplc_user_default_visitor_name'],
642
- 'email' => 'none',
643
- 'session' => '1',
644
- 'ip' => wplc_get_user_ip(),
645
- 'url' => '',
646
- 'last_active_timestamp' => current_time('mysql'),
647
- 'other' => '',
648
- 'agent_id' => $aid,
649
- 'rel' => $cid,
650
- ),
651
- array(
652
- '%s',
653
- '%s',
654
- '%s',
655
- '%s',
656
- '%s',
657
- '%s',
658
- '%s',
659
- '%s',
660
- '%s',
661
- '%d',
662
- '%s'
663
- )
664
- );
665
-
666
-
667
- $cid = $wpdb->insert_id;
668
- do_action("wplc_hook_update_agent_id",$cid,$aid);
669
-
670
- }
671
-
672
-
673
-
674
- } else {
675
- $return_array['response'] = "No 'AID' found (base64 encoded)";
676
- $return_array['code'] = "401";
677
- $return_array['requirements'] = array(
678
- "security" => "YOUR_SECRET_TOKEN",
679
- "cid" => "Chat ID",
680
- "aid" => "agent ID");
681
- }
682
-
683
- } else {
684
- $return_array['response'] = "No 'REL' or 'CID' found (base64 encoded)";
685
- $return_array['code'] = "401";
686
- $return_array['requirements'] = array(
687
- "security" => "YOUR_SECRET_TOKEN",
688
- "cid" => "Chat ID",
689
- "rel/cid" => "related ID or Chat ID");
690
- }
691
-
692
-
693
-
694
-
695
- } else {
696
- $return_array['response'] = "Nonce is invalid";
697
- $return_array['code'] = "401";
698
- }
699
- } else {
700
- $return_array['response'] = "No 'security' found";
701
- $return_array['code'] = "401";
702
- $return_array['requirements'] = array(
703
- "security" => "YOUR_SECRET_TOKEN",
704
- "cid" => "Chat ID",
705
- "wplc_extra_data" => "Data array");
706
- }
707
- } else {
708
- $return_array['response'] = "No request data found";
709
- $return_array['code'] = "400";
710
- $return_array['requirements'] = array(
711
- "security" => "YOUR_SECRET_TOKEN",
712
- "cid" => "Chat ID",
713
- "wplc_extra_data" => "Data array");
714
- }
715
-
716
- return $return_array;
717
  }
718
 
719
  function wplc_api_agent_email_notification_mrg(WP_REST_Request $request) { // TODO: this function is never referenced
@@ -726,7 +744,7 @@ function wplc_api_agent_email_notification_mrg(WP_REST_Request $request) { // TO
726
  if (isset($request['wplc_extra_data'])) {
727
  // TODO: this code does nothing useful
728
  $data = $request['wplc_extra_data'];
729
- $wplc_settings = wplc_get_options();
730
  $email_address = wplc_determine_admin_email($wplc_settings);
731
  return true;
732
  } else {
@@ -735,15 +753,17 @@ function wplc_api_agent_email_notification_mrg(WP_REST_Request $request) { // TO
735
  $return_array['requirements'] = array(
736
  "security" => "YOUR_SECRET_TOKEN",
737
  "cid" => "Chat ID",
738
- "wplc_extra_data" => "Data array");
739
- }
740
- } else {
741
- $return_array['response'] = "No 'CID' found";
742
- $return_array['code'] = "401";
743
- $return_array['requirements'] = array(
744
- "security" => "YOUR_SECRET_TOKEN",
745
- "cid" => "Chat ID",
746
- "wplc_extra_data" => "Data array");
 
 
747
  }
748
  } else {
749
  $return_array['response'] = "Nonce is invalid";
@@ -770,218 +790,229 @@ function wplc_api_agent_email_notification_mrg(WP_REST_Request $request) { // TO
770
  return $return_array;
771
  }
772
 
773
- function wplc_api_agent_is_typing_mrg(WP_REST_Request $request){
774
-
775
- $return_array = array();
776
- if(isset($request)){
777
- if(isset($request['security'])){
778
- $check_token = get_option('wplc_api_secret_token');
779
- if($check_token !== false && $request['security'] === $check_token){
780
- if(isset($request['cid'])){
781
- if(isset($request['user'])){
782
- if(isset($request['type'])){
783
- if (wplc_typing_mrg($request['user'],sanitize_text_field($request['cid']),sanitize_text_field($request['type']))) {
784
-
785
- $return_array['response'] = "Successful";
786
- $return_array['code'] = "200";
787
- $return_array['data'] = array("cid" => intval($request['cid']),
788
- "user" => intval($request['user']),
789
- "type" => intval($request['type']));
790
- } else {
791
- $return_array['response'] = "Failed to send typing indicaator";
792
- $return_array['code'] = "401";
793
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
794
- "cid" => "Chat ID",
795
- "user" => "User type",
796
- 'type' => "TYPE");
797
-
798
- }
799
- } else {
800
-
801
- $return_array['response'] = "No 'type' found";
802
- $return_array['code'] = "401";
803
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
804
- "cid" => "Chat ID",
805
- "user" => "User type",
806
- 'type' => "TYPE");
807
- }
808
-
809
- } else {
810
- $return_array['response'] = "No 'user' found";
811
- $return_array['code'] = "401";
812
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
813
- "cid" => "Chat ID",
814
- "user" => "User type",
815
- 'type' => "TYPE");
816
- }
817
- } else {
818
- $return_array['response'] = "No 'cid' found";
819
- $return_array['code'] = "401";
820
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
821
- "cid" => "Chat ID",
822
- "user" => "User type",
823
- 'type' => "TYPE");
824
- }
825
- } else {
826
- $return_array['response'] = "Nonce is invalid";
827
- $return_array['code'] = "401";
828
- }
829
- } else{
830
- $return_array['response'] = "No 'security' found";
831
- $return_array['code'] = "401";
832
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
833
- "cid" => "Chat ID",
834
- "user" => "User type",
835
- 'type' => "TYPE");
836
- }
837
- }else{
838
- $return_array['response'] = "No request data found";
839
- $return_array['code'] = "400";
840
- $return_array['requirements'] = array("security" => "YOUR_SECRET_TOKEN",
841
- "cid" => "Chat ID",
842
- "user" => "User type",
843
- 'type' => "TYPE");
844
- }
845
-
846
- return $return_array;
 
 
 
 
 
 
 
 
 
 
 
 
847
  }
848
 
849
 
850
  function wplc_api_record_agent_chat_msg_mrg($from, $cid, $msg, $rest_check = false, $ato = false, $other = false, $orig_override = false) {
851
- global $wpdb;
852
- global $wplc_tblname_msgs;
853
 
854
 
855
-
856
- if( ! filter_var($cid, FILTER_VALIDATE_INT) ) {
857
-
858
- /**
859
- * We need to identify if this CID is a node CID, and if so, return the WP CID from the wplc_chat_msgs table
860
- */
861
- $cid = wplc_return_chat_id_by_rel($cid);
862
- }
863
 
864
  /**
865
- * check if this CID even exists, if not, create it
866
- *
867
- * If it doesnt exist, it most likely is an agent-to-agent chat that we now need to save.
868
  */
869
-
870
- global $wplc_tblname_chats;
871
- $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `rel` = %s OR `id` = %s LIMIT 1", $cid, $cid));
872
- if (!$results) {
873
- /* it doesnt exist, lets put it in the table */
874
-
875
- $wpdb->insert(
876
- $wplc_tblname_chats,
877
- array(
878
- 'status' => 3,
879
- 'timestamp' => current_time('mysql'),
880
- 'name' => 'agent-to-agent chat',
881
- 'email' => 'none',
882
- 'session' => '1',
883
- 'ip' => wplc_get_user_ip(),
884
- 'url' => '',
885
- 'last_active_timestamp' => current_time('mysql'),
886
- 'other' => '',
887
- 'rel' => $cid,
888
- ),
889
- array(
890
- '%s',
891
- '%s',
892
- '%s',
893
- '%s',
894
- '%s',
895
- '%s',
896
- '%s',
897
- '%s',
898
- '%s',
899
- '%s'
900
- )
901
- );
902
-
903
-
904
- $cid = $wpdb->insert_id;
905
- }
 
 
 
 
906
 
907
- $msg_id = '';
908
- if ($other !== false) {
909
- if (!empty($other->msgID)) {
910
- $msg_id = $other->msgID;
911
- } else {
912
- $msg_id = '';
913
- }
914
- }
915
 
916
- $user_info = get_userdata( $from );
917
- if( $user_info ){
918
- $fromname = $user_info->display_name;
 
 
 
 
919
  } else {
920
- $fromname = 'agent';
921
- }
922
- $orig = '1';
923
- if($orig_override !== false){
924
- $orig = sanitize_text_field($orig_override);
925
  }
 
926
 
927
- $orig_msg = $msg;
928
-
929
- $msg = apply_filters("wplc_filter_message_control",$msg);
930
-
931
-
932
- $wpdb->insert(
933
- $wplc_tblname_msgs,
934
- array(
935
- 'chat_sess_id' => $cid,
936
- 'timestamp' => current_time('mysql'),
937
- 'msgfrom' => $fromname,
938
- 'msg' => $msg,
939
- 'status' => 0,
940
- 'originates' => $orig,
941
- 'other' => '',
942
- 'rel' => $msg_id,
943
- 'ato' => $ato,
944
- 'afrom' => $from
945
- ),
946
- array(
947
- '%s',
948
- '%s',
949
- '%s',
950
- '%s',
951
- '%d',
952
- '%s',
953
- '%s',
954
- '%s',
955
- '%d',
956
- '%d'
957
- )
958
- );
959
-
960
- $data = array(
961
- 'cid' => $cid,
962
- 'from' => $from,
963
- 'msg' => $orig_msg,
964
- 'orig' => $orig
965
- );
966
- //do_action("wplc_hook_message_sent",$data);
967
-
968
- wplc_update_active_timestamp(sanitize_text_field($cid));
969
-
970
-
971
- return true;
972
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  }
974
 
975
  add_filter("wplc_api_remote_upload_filter", "wplc_api_agent_remote_upload_handler_mrg", 10, 2);
976
  /*
977
  * Processes remote uploads, from app or main agent files as an example
978
  */
979
- function wplc_api_agent_remote_upload_handler_mrg($return_array, $request) {
980
  $remote_files = $request->get_file_params();
981
  if (is_array($remote_files)) {
982
  $upload_dir = wp_upload_dir();
983
  $user_dirname = $upload_dir['basedir'];
984
- $cid=0;
985
  if (isset($request['cid'])) {
986
  $cid = sanitize_text_field($request['cid']);
987
  if (!filter_var($cid, FILTER_VALIDATE_INT)) {
@@ -991,24 +1022,24 @@ function wplc_api_agent_remote_upload_handler_mrg($return_array, $request) {
991
  $cid = intval($cid);
992
  }
993
 
994
- if (!file_exists( $user_dirname."/wp_live_chat/")) {
995
- @mkdir($user_dirname.'/wp_live_chat/');
996
- }
997
 
998
- if (!realpath($user_dirname."/wp_live_chat/".$cid)) {
999
- @mkdir( $user_dirname.'/wp_live_chat/'. $cid );
1000
- }
1001
 
1002
  if (isset($remote_files['file'])) {
1003
- $file_name = strtolower(sanitize_file_name($remote_files['file']['name']) );
1004
  $file_name = basename($file_name); //This prevents traversal
1005
  $file_name = str_replace(" ", "_", $file_name);
1006
  if (wplc_check_file_name_for_safe_extension($file_name)) {
1007
- if (realpath($user_dirname . "/wp_live_chat/" . $cid . "/" . $file_name ) == false) {
1008
  $file_name = rand(0, 10) . "-" . $file_name;
1009
- }
1010
- if (move_uploaded_file($remote_files['file']['tmp_name'], $user_dirname."/wp_live_chat/" . $cid . "/" . $file_name)) {
1011
- $response = $upload_dir['baseurl']."/wp_live_chat/" . $cid . "/" . $file_name;
1012
  $return_array['response'] = wp_filter_post_kses(strip_tags($response));
1013
  } else {
1014
  $return_array['response'] = __('Upload error', 'wp-live-chat-support');
@@ -1027,16 +1058,16 @@ function wplc_api_agent_remote_upload_handler_mrg($return_array, $request) {
1027
 
1028
  /**
1029
  * Cleanup all REST Params
1030
- */
1031
- function wplc_api_agent_sanitize_request_params(WP_REST_Request $request){
1032
- global $wpdb;
1033
-
1034
- $params = $request->get_params();
1035
- foreach ($params as $key => $value) {
1036
- if(is_string($value)){
1037
- $request->set_param($key, $wpdb->_real_escape($value));
1038
- }
1039
- }
1040
 
1041
- return $request;
1042
  }
1
+ <?php
2
  /* Handles all functions related to the WP Live Chat Support API */
3
 
4
+ if (!defined('ABSPATH')) {
5
+ exit;
6
  }
7
 
8
 
13
  * - Chat ID
14
  * - Agent ID
15
  */
16
+ function wplc_api_accept_chat(WP_REST_Request $request) {
17
+
18
+ $return_array = array();
19
+ if (isset($request)) {
20
+ if (isset($request['token'])) {
21
+ $check_token = get_option('wplc_api_secret_token');
22
+ if ($check_token !== false && $request['token'] === $check_token) {
23
+ if (isset($request['chat_id'])) {
24
+ if (isset($request['agent_id'])) {
25
+
26
+ $cid = wplc_return_chat_id_by_rel($request['chat_id']);
27
+ if (wplc_change_chat_status($cid, 3, intval($request['agent_id']))) {
28
+
29
+
30
+ do_action("wplc_hook_update_agent_id", sanitize_text_field($request['cid']), intval($request['agent_id']));
31
+
32
+ $return_array['response'] = "Chat accepted successfully";
33
+ $return_array['code'] = "200";
34
+ $return_array['data'] = array(
35
+ "chat_id" => intval($request['chat_id']),
36
+ "agent_id" => intval($request['agent_id'])
37
+ );
38
+ } else {
39
+ $return_array['response'] = "Status could not be changed";
40
+ $return_array['code'] = "404";
41
+ }
42
+ } else {
43
+ $return_array['response'] = "No 'agent_id' found";
44
+ $return_array['code'] = "401";
45
+ $return_array['requirements'] = array(
46
+ "token" => "YOUR_SECRET_TOKEN",
47
+ "chat_id" => "Chat ID",
48
+ "agent_id" => "Agent ID"
49
+ );
50
+ }
51
+ } else {
52
+ $return_array['response'] = "No 'chat_id' found";
53
+ $return_array['code'] = "401";
54
+ $return_array['requirements'] = array(
55
+ "token" => "YOUR_SECRET_TOKEN",
56
+ "chat_id" => "Chat ID",
57
+ "agent_id" => "Agent ID"
58
+ );
59
+ }
60
+ } else {
61
+ $return_array['response'] = "Secret token is invalid";
62
+ $return_array['code'] = "401";
63
+ }
64
+ } else {
65
+ $return_array['response'] = "No secret 'token' found";
66
+ $return_array['code'] = "401";
67
+ $return_array['requirements'] = array(
68
+ "token" => "YOUR_SECRET_TOKEN",
69
+ "chat_id" => "Chat ID",
70
+ "agent_id" => "Agent ID"
71
+ );
72
+ }
73
+ } else {
74
+ $return_array['response'] = "No request data found";
75
+ $return_array['code'] = "400";
76
+ $return_array['requirements'] = array(
77
+ "token" => "YOUR_SECRET_TOKEN",
78
+ "chat_id" => "Chat ID",
79
+ "agent_id" => "Agent ID"
80
+ );
81
+ }
82
+
83
+ return $return_array;
84
  }
85
 
86
  /*
90
  * - Chat ID
91
  * - Agent ID
92
  */
93
+ function wplc_api_agent_end_chat(WP_REST_Request $request) {
94
+
95
+ $return_array = array();
96
+ if (isset($request)) {
97
+ if (isset($request['token'])) {
98
+ $check_token = get_option('wplc_api_secret_token');
99
+ if ($check_token !== false && $request['token'] === $check_token) {
100
+ if (isset($request['chat_id'])) {
101
+ if (isset($request['agent_id'])) {
102
+
103
+ $cid = $request['chat_id'];
104
+ if (!filter_var($request['chat_id'], FILTER_VALIDATE_INT)) {
105
+ /* We need to identify if this CID is a node CID, and if so, return the WP CID */
106
+ $cid = wplc_return_chat_id_by_rel($cid);
107
+ }
108
+
109
+ if (wplc_change_chat_status($cid, 1, intval($request['agent_id']))) {
110
+
111
+ do_action('wplc_send_transcript_hook', $cid);
112
+
113
+ $return_array['response'] = "Chat ended successfully";
114
+ $return_array['code'] = "200";
115
+ $return_array['data'] = array(
116
+ "chat_id" => $cid,
117
+ "agent_id" => intval($request['agent_id'])
118
+ );
119
+ } else {
120
+ $return_array['response'] = "Status could not be changed";
121
+ $return_array['code'] = "404";
122
+ }
123
+ } else {
124
+ $return_array['response'] = "No 'agent_id' found";
125
+ $return_array['code'] = "401";
126
+ $return_array['requirements'] = array(
127
+ "token" => "YOUR_SECRET_TOKEN",
128
+ "chat_id" => "Chat ID",
129
+ "agent_id" => "Agent ID"
130
+ );
131
+ }
132
+ } else {
133
+ $return_array['response'] = "No 'chat_id' found";
134
+ $return_array['code'] = "401";
135
+ $return_array['requirements'] = array(
136
+ "token" => "YOUR_SECRET_TOKEN",
137
+ "chat_id" => "Chat ID",
138
+ "agent_id" => "Agent ID"
139
+ );
140
+ }
141
+ } else {
142
+ $return_array['response'] = "Secret token is invalid";
143
+ $return_array['code'] = "401";
144
+ }
145
+ } else {
146
+ $return_array['response'] = "No secret 'token' found";
147
+ $return_array['code'] = "401";
148
+ $return_array['requirements'] = array(
149
+ "token" => "YOUR_SECRET_TOKEN",
150
+ "chat_id" => "Chat ID",
151
+ "agent_id" => "Agent ID"
152
+ );
153
+ }
154
+ } else {
155
+ $return_array['response'] = "No request data found";
156
+ $return_array['code'] = "400";
157
+ $return_array['requirements'] = array(
158
+ "token" => "YOUR_SECRET_TOKEN",
159
+ "chat_id" => "Chat ID",
160
+ "agent_id" => "Agent ID"
161
+ );
162
+ }
163
+
164
+ return $return_array;
165
  }
166
 
167
 
173
  * - Chat ID
174
  * - Message
175
  */
176
+ function wplc_api_agent_send_message(WP_REST_Request $request) {
177
+
178
+ $return_array = array();
179
+ if (isset($request)) {
180
+ if (isset($request['server_token'])) {
181
+ $check_token = get_option('wplc_api_secret_token');
182
+ if ($check_token !== false && $request['server_token'] === $check_token) {
183
+ if (isset($request['chat_id'])) {
184
+ if (isset($request['message'])) {
185
+ if (isset($request['relay_action'])) {
186
+
187
+ $chat_id = sanitize_text_field($request['chat_id']);
188
+ $message = $request['message'];
189
+ $action = $request['relay_action'];
190
+
191
+ if (!empty($request['msg_id'])) {
192
+ $other = new stdClass();
193
+ $other->msgID = $request['msg_id'];
194
+ } else {
195
+ $other = false;
196
+ }
197
+
198
+ if ($action == "wplc_admin_send_msg") {
199
+ wplc_record_chat_msg("2", $chat_id, $message, true, sanitize_text_field($request['agent_id']), $other);
200
+ wplc_update_active_timestamp($chat_id);
201
+
202
+ $return_array['response'] = "Message sent successfully";
203
+ $return_array['code'] = "200";
204
+ $return_array['data'] = array(
205
+ "chat_id" => sanitize_text_field($request['chat_id']),
206
+ "agent_id" => intval($request['agent_id'])
207
+ );
208
+
209
+ do_action("wplc_new_user_message_after_record_hook", $chat_id, $message);
210
+ }
211
+ } else {
212
+ $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
213
+ }
214
+ } else {
215
+ $return_array['response'] = "No 'message' found";
216
+ $return_array['code'] = "401";
217
+ $return_array['requirements'] = array(
218
+ "server_token" => "YOUR_SECRET_TOKEN",
219
+ "chat_id" => "Chat ID",
220
+ "message" => "Message"
221
+ );
222
+ }
223
+ } else {
224
+ $return_array['response'] = "No 'chat_id' found";
225
+ $return_array['code'] = "401";
226
+ $return_array['requirements'] = array(
227
+ "server_token" => "YOUR_SECRET_TOKEN",
228
+ "chat_id" => "Chat ID",
229
+ "message" => "Message"
230
+ );
231
+ }
232
+ } else {
233
+ $return_array['response'] = "Secret server_token is invalid";
234
+ $return_array['code'] = "401";
235
+ }
236
+ } else {
237
+ $return_array['response'] = "No secret 'server_token' found";
238
+ $return_array['code'] = "401";
239
+ $return_array['requirements'] = array(
240
+ "server_token" => "YOUR_SECRET_TOKEN",
241
+ "chat_id" => "Chat ID",
242
+ "message" => "Message"
243
+ );
244
+ }
245
+ } else {
246
+ $return_array['response'] = "No request data found";
247
+ $return_array['code'] = "400";
248
+ $return_array['requirements'] = array(
249
+ "server_token" => "YOUR_SECRET_TOKEN",
250
+ "chat_id" => "Chat ID",
251
+ "message" => "Message"
252
+ );
253
+ }
254
+
255
+ return $return_array;
256
  }
257
 
258
 
266
  * - Limit (Defaults to 50/Max Limit of 50)
267
  * - Offset (Defaults to 0)
268
  */
269
+ function wplc_api_agent_get_messages(WP_REST_Request $request) {
270
+
271
+ $return_array = array();
272
+ if (isset($request)) {
273
+ if (isset($request['token'])) {
274
+ $check_token = get_option('wplc_api_secret_token');
275
+ if ($check_token !== false && $request['token'] === $check_token) {
276
+ if (isset($request['chat_id'])) {
277
+ $limit = 50;
278
+ $offset = 0;
279
+ if (isset($request['limit'])) {
280
+ $limit = intval($request['limit']);
281
+ }
282
+ if (isset($request['offset'])) {
283
+ $offset = intval($request['offset']);
284
+ }
285
+
286
+ if (isset($request['received_via'])) {
287
+ $received_via = sanitize_text_field($request['received_via']);
288
+ } else {
289
+ $received_via = 'u';
290
+ }
291
+
292
+ $message_data = wplc_api_return_messages($request['chat_id'], $limit, $offset, $received_via);
293
+
294
+ if ($message_data) {
295
+ $return_array['response'] = "Message data returned";
296
+ $return_array['code'] = "200";
297
+ $return_array['data'] = array("messages" => $message_data);
298
+ } else {
299
+ $return_array['response'] = "Messages not found";
300
+ $return_array['code'] = "404";
301
+ $return_array['data'] = array("chat_id" => intval($request['chat_id']));
302
+ }
303
+ } else {
304
+ $return_array['response'] = "No 'chat_id' found";
305
+ $return_array['code'] = "401";
306
+ $return_array['requirements'] = array(
307
+ "token" => "YOUR_SECRET_TOKEN",
308
+ "chat_id" => "Chat ID"
309
+ );
310
+ }
311
+ } else {
312
+ $return_array['response'] = "Secret token is invalid";
313
+ $return_array['code'] = "401";
314
+ }
315
+ } else {
316
+ $return_array['response'] = "No secret 'token' found";
317
+ $return_array['code'] = "401";
318
+ $return_array['requirements'] = array(
319
+ "token" => "YOUR_SECRET_TOKEN",
320
+ "chat_id" => "Chat ID"
321
+ );
322
+ }
323
+ } else {
324
+ $return_array['response'] = "No request data found";
325
+ $return_array['code'] = "400";
326
+ $return_array['requirements'] = array(
327
+ "token" => "YOUR_SECRET_TOKEN",
328
+ "chat_id" => "Chat ID"
329
+ );
330
+ }
331
+
332
+ return $return_array;
333
  }
334
 
335
 
336
  /*
337
  * Records an admin message via the API
338
  */
339
+ function wplc_api_agent_record_admin_message($cid, $msg) {
340
+
341
+ global $wpdb;
342
+ global $wplc_tblname_msgs;
343
+
344
+ $fromname = apply_filters("wplc_filter_admin_name", "Admin");
345
+ $orig = '1';
346
+
347
+ $msg = apply_filters("wplc_filter_message_control", $msg);
348
+
349
+ $wpdb->insert(
350
+ $wplc_tblname_msgs,
351
+ array(
352
+ 'chat_sess_id' => $cid,
353
+ 'timestamp' => current_time('mysql'),
354
+ 'msgfrom' => $fromname,
355
+ 'msg' => $msg,
356
+ 'status' => 0,
357
+ 'originates' => $orig
358
+ ),
359
+ array(
360
+ '%s',
361
+ '%s',
362
+ '%s',
363
+ '%s',
364
+ '%d',
365
+ '%s'
366
+ )
367
+ );
368
+
369
+ wplc_update_active_timestamp(sanitize_text_field($cid));
370
+ wplc_change_chat_status(sanitize_text_field($cid), 3);
371
+
372
+ return true;
373
  }
374
 
375
  /*
376
  * Returns messages from server
377
  */
378
+ function wplc_api_agent_return_messages($cid, $limit, $offset, $received_via = 'u') {
379
+ $cid = wplc_return_chat_id_by_rel($cid);
380
+ $messages = wplc_return_chat_messages($cid, false, true, false, false, 'array', false);
381
+ if ($received_via === 'u') {
382
+ wplc_mark_as_read_user_chat_messages($cid);
383
+ } else {
384
+ wplc_mark_as_read_agent_chat_messages($cid, $received_via);
385
+ }
386
+ return $messages;
387
+ }
388
+
389
 
390
+ function wplc_api_agent_return_sessions() {
391
+ global $wpdb;
392
+ global $wplc_tblname_chats;
393
 
394
+ $results = $wpdb->get_results("SELECT * FROM $wplc_tblname_chats WHERE `status` = 3 OR `status` = 2 OR `status` = 10 OR `status` = 5 or `status` = 8 or `status` = 9 ORDER BY `timestamp` ASC");
395
 
396
+ $session_array = array();
 
 
 
 
 
397
 
398
+ if ($results) {
399
+ foreach ($results as $result) {
400
+ $ip_info = maybe_unserialize($result->ip);
401
+ $user_ip = $ip_info['ip'];
402
+ if ($user_ip == "") {
403
+ $user_ip = __('IP Address not recorded', 'wp-live-chat-support');
404
+ }
405
 
406
+ $browser = 'Unknown';
407
+ $browser_image = '';
408
+ if (!empty($ip_info['user_agent'])) {
409
+ $browser = wplc_return_browser_string($ip_info['user_agent']);
410
+ $browser_image = wplc_return_browser_image($browser, "16");
411
+ }
412
 
413
 
414
+ $session_array[$result->id] = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
+ $session_array[$result->id]['name'] = $result->name;
417
+ $session_array[$result->id]['email'] = $result->email;
418
+
419
+ $session_array[$result->id]['status'] = $result->status;
420
+ $session_array[$result->id]['timestamp'] = wplc_time_ago($result->timestamp);
421
+
422
+ if ((current_time('timestamp') - strtotime($result->timestamp)) < 3600) {
423
+ $session_array[$result->id]['type'] = __("New", 'wp-live-chat-support');
424
+ } else {
425
+ $session_array[$result->id]['type'] = __("Returning", 'wp-live-chat-support');
426
+ }
427
+
428
+ $session_array[$result->id]['image'] = "//www.gravatar.com/avatar/" . md5($result->email) . "?s=30&d=mm";
429
+ $session_array[$result->id]['data']['browsing'] = $result->url;
430
+ $path = parse_url($result->url, PHP_URL_PATH);
431
+
432
+ if (strlen($path) > 20) {
433
+ $session_array[$result->id]['data']['browsing_nice_url'] = substr($path, 0, 20) . '...';
434
+ } else {
435
+ $session_array[$result->id]['data']['browsing_nice_url'] = $path;
436
+ }
437
+
438
+ $session_array[$result->id]['data']['browser'] = WPLC_PLUGIN_URL . "images/$browser_image";
439
+ $session_array[$result->id]['data']['ip'] = $user_ip;
 
 
 
 
 
 
 
 
 
 
 
440
  }
441
+ }
442
+
443
+ return $session_array;
444
  }
445
 
446
 
453
  /*
454
  * Upload end point
455
  */
456
+ function wplc_api_remote_upload(WP_REST_Request $request) {
457
+ $return_array = array();
458
+ $return_array['response'] = 'false';
459
+ $return_array = apply_filters("wplc_api_remote_upload_filter", $return_array, $request);
460
+ return $return_array;
 
 
 
461
  }
462
 
463
  /*
464
  * Rest Permission check for restricted end points
465
  */
466
+ function wplc_api_agent_permission_check() {
467
+ if (is_user_logged_in() && wplc_user_is_agent()) {
468
+ return true;
469
+ } else {
470
+ return false;
471
+ }
472
+ }
473
+
474
+ function wplc_agent_validate_agent_check(WP_REST_Request $request) {
475
+ $return_array = array();
476
+ if (isset($request)) {
477
+ if (isset($request['agent_id'])) {
478
+ if (wplc_user_is_agent(intval($request['agent_id']))) {
479
+ $return_array['response'] = "true";
480
+ $return_array['code'] = "200";
481
+ } else {
482
+ $return_array['response'] = "false";
483
+ $return_array['code'] = "200";
484
+ }
485
+ } else {
486
+ $return_array['response'] = "No Agent ID found";
487
+ $return_array['code'] = "401";
488
+ $return_array['requirements'] = array("agent_id" => "Agent ID");
489
+ }
490
+ } else {
491
+ $return_array['response'] = "No request data found";
492
+ $return_array['code'] = "400";
493
+ $return_array['requirements'] = array("agent_id" => "Agent ID");
494
+ }
495
+
496
+ return $return_array;
497
  }
498
 
 
499
 
500
+ # PRO API FUNCTIONS
501
+ function wplc_api_send_agent_message_mrg(WP_REST_Request $request) {
502
+ $return_array = array();
503
+ if (isset($request)) {
504
+ if (isset($request['server_token'])) {
505
+ $check_token = get_option('wplc_api_secret_token');
506
+ if ($check_token !== false && $request['server_token'] === $check_token) {
507
+ if (isset($request['chat_id'])) {
508
+ if (isset($request['message'])) {
509
+ if (isset($request['relay_action'])) {
510
+
511
+ $chat_id = sanitize_text_field($request['chat_id']);
512
+ $message = $request['message'];
513
+ $action = $request['relay_action'];
514
+
515
+ if (!empty($request['msg_id'])) {
516
+ $other = new stdClass();
517
+ $other->msgID = $request['msg_id'];
518
+ } else {
519
+ $other = false;
520
+ }
521
+
522
+ if ($action == "wplc_admin_send_msg") {
523
+ $message = sanitize_text_field($message);
524
+ $ato = intval($request['ato']);
525
+ if (isset($request['orig_override'])) {
526
+ wplc_api_record_agent_chat_msg_mrg(sanitize_text_field($request['agent_id']), $chat_id, $message, true, $ato, $other, $request['orig_override']);
527
+ } else {
528
+ wplc_api_record_agent_chat_msg_mrg(sanitize_text_field($request['agent_id']), $chat_id, $message, true, $ato, $other);
529
+ }
530
+ wplc_update_active_timestamp($chat_id);
531
+
532
+ $return_array['response'] = "Message sent successfully";
533
  $return_array['code'] = "200";
534
+ $return_array['data'] = array(
535
+ "chat_id" => intval($request['chat_id']),
536
+ "agent_id" => intval($request['agent_id'])
537
+ );
538
+
539
+ do_action("wplc_new_user_message_after_record_hook", $chat_id, $message);
540
+ }
541
  } else {
542
+ $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
 
543
  }
544
+ } else {
545
+ $return_array['response'] = "No 'message' found";
546
  $return_array['code'] = "401";
547
+ $return_array['requirements'] = array(
548
+ "server_token" => "YOUR_SECRET_TOKEN",
549
+ "chat_id" => "Chat ID",
550
+ "message" => "Message"
551
+ );
552
+ }
553
+ } else {
554
+ $return_array['response'] = "No 'chat_id' found";
555
+ $return_array['code'] = "401";
556
+ $return_array['requirements'] = array(
557
+ "server_token" => "YOUR_SECRET_TOKEN",
558
+ "chat_id" => "Chat ID",
559
+ "message" => "Message"
560
+ );
561
  }
562
+ } else {
563
+ $return_array['response'] = "Secret server_token is invalid";
564
+ $return_array['code'] = "401";
565
+ }
566
+ } else {
567
+ $return_array['response'] = "No secret 'server_token' found";
568
+ $return_array['code'] = "401";
569
+ $return_array['requirements'] = array(
570
+ "server_token" => "YOUR_SECRET_TOKEN",
571
+ "chat_id" => "Chat ID",
572
+ "message" => "Message"
573
+ );
574
  }
575
+ } else {
576
+ $return_array['response'] = "No request data found";
577
+ $return_array['code'] = "400";
578
+ $return_array['requirements'] = array(
579
+ "server_token" => "YOUR_SECRET_TOKEN",
580
+ "chat_id" => "Chat ID",
581
+ "message" => "Message"
582
+ );
583
+ }
584
+
585
+ return $return_array;
586
  }
587
 
588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
 
590
+ function wplc_api_get_agent_unread_message_counts_mrg(WP_REST_Request $request) {
591
+ $return_array = array();
592
+ if (isset($request)) {
593
+ if (isset($request['token'])) {
594
+ $check_token = get_option('wplc_api_secret_token');
595
+ if ($check_token !== false && $request['token'] === $check_token) {
596
+
597
+ $current_agent = intval(sanitize_text_field($request['agent_id']));
598
 
599
+ /**
600
+ * Get all agents
601
+ * @var [type]
602
+ */
603
+ $user_array = wplc_get_agent_users();
604
+ $a_array = array();
605
+ if ($user_array) {
606
+ foreach ($user_array as $user) {
607
+ $unread = wplc_return_unread_agent_messages_mrg($current_agent, $user->ID);
608
+ $a_array[$user->ID] = $unread;
609
+ }
610
+ }
611
+ $return_array['response'] = "Unread count agents"; /* needs to be exactly this for the JS to fire correctly */
612
+ $return_array['code'] = "200";
613
+ $return_array['data'] = $a_array;
614
+ } else {
615
+ $return_array['response'] = "Secret token is invalid";
616
+ $return_array['code'] = "401";
617
+ }
618
+ } else {
619
+ $return_array['response'] = "No secret 'token' found";
620
+ $return_array['code'] = "401";
621
+ $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN");
622
+ }
623
+ } else {
624
+ $return_array['response'] = "No request data found";
625
+ $return_array['code'] = "400";
626
+ $return_array['requirements'] = array("token" => "YOUR_SECRET_TOKEN");
627
+ }
628
 
629
+ return $return_array;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  }
631
 
632
  function wplc_api_initiate_chat_mrg(WP_REST_REQUEST $request) {
633
  $wplc_settings = wplc_get_options();
634
+ $return_array = array();
635
+ if (isset($request)) {
636
+ if (isset($request['security'])) {
637
+ $check_token = get_option('wplc_api_secret_token');
638
+ if ($check_token !== false && $request['token'] === $check_token) {
639
+
640
+ if (isset($request['rel']) || isset($request['cid'])) {
641
+
642
+ if (isset($request['aid'])) {
643
+
644
+ $aid = intval($request['aid']);
645
+
646
+ if (isset($request['rel'])) {
647
+ $cid = $request['rel'];
648
+ } else {
649
+ $cid = $request['cid'];
650
+ }
651
+
652
+
653
+ global $wplc_tblname_chats;
654
+ global $wpdb;
655
+ $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `rel` = %s OR `id` = %s LIMIT 1", $cid, $cid));
656
+ if (!$results) {
657
+ /* it doesnt exist, lets put it in the table */
658
+
659
+ $wpdb->insert(
660
+ $wplc_tblname_chats,
661
+ array(
662
+ 'status' => 3,
663
+ 'timestamp' => current_time('mysql'),
664
+ 'name' => $wplc_settings['wplc_user_default_visitor_name'],
665
+ 'email' => 'none',
666
+ 'session' => '1',
667
+ 'ip' => wplc_get_user_ip(),
668
+ 'url' => '',
669
+ 'last_active_timestamp' => current_time('mysql'),
670
+ 'other' => '',
671
+ 'agent_id' => $aid,
672
+ 'rel' => $cid,
673
+ ),
674
+ array(
675
+ '%s',
676
+ '%s',
677
+ '%s',
678
+ '%s',
679
+ '%s',
680
+ '%s',
681
+ '%s',
682
+ '%s',
683
+ '%s',
684
+ '%d',
685
+ '%s'
686
+ )
687
+ );
688
+
689
+
690
+ $cid = $wpdb->insert_id;
691
+ do_action("wplc_hook_update_agent_id", $cid, $aid);
692
+ }
693
+ } else {
694
+ $return_array['response'] = "No 'AID' found (base64 encoded)";
695
+ $return_array['code'] = "401";
696
+ $return_array['requirements'] = array(
697
+ "security" => "YOUR_SECRET_TOKEN",
698
+ "cid" => "Chat ID",
699
+ "aid" => "agent ID"
700
+ );
701
+ }
702
+ } else {
703
+ $return_array['response'] = "No 'REL' or 'CID' found (base64 encoded)";
704
+ $return_array['code'] = "401";
705
+ $return_array['requirements'] = array(
706
+ "security" => "YOUR_SECRET_TOKEN",
707
+ "cid" => "Chat ID",
708
+ "rel/cid" => "related ID or Chat ID"
709
+ );
710
+ }
711
+ } else {
712
+ $return_array['response'] = "Nonce is invalid";
713
+ $return_array['code'] = "401";
714
+ }
715
+ } else {
716
+ $return_array['response'] = "No 'security' found";
717
+ $return_array['code'] = "401";
718
+ $return_array['requirements'] = array(
719
+ "security" => "YOUR_SECRET_TOKEN",
720
+ "cid" => "Chat ID",
721
+ "wplc_extra_data" => "Data array"
722
+ );
723
+ }
724
+ } else {
725
+ $return_array['response'] = "No request data found";
726
+ $return_array['code'] = "400";
727
+ $return_array['requirements'] = array(
728
+ "security" => "YOUR_SECRET_TOKEN",
729
+ "cid" => "Chat ID",
730
+ "wplc_extra_data" => "Data array"
731
+ );
732
+ }
733
+
734
+ return $return_array;
 
 
 
 
 
735
  }
736
 
737
  function wplc_api_agent_email_notification_mrg(WP_REST_Request $request) { // TODO: this function is never referenced
744
  if (isset($request['wplc_extra_data'])) {
745
  // TODO: this code does nothing useful
746
  $data = $request['wplc_extra_data'];
747
+ $wplc_settings = wplc_get_options();
748
  $email_address = wplc_determine_admin_email($wplc_settings);
749
  return true;
750
  } else {
753
  $return_array['requirements'] = array(
754
  "security" => "YOUR_SECRET_TOKEN",
755
  "cid" => "Chat ID",
756
+ "wplc_extra_data" => "Data array"
757
+ );
758
+ }
759
+ } else {
760
+ $return_array['response'] = "No 'CID' found";
761
+ $return_array['code'] = "401";
762
+ $return_array['requirements'] = array(
763
+ "security" => "YOUR_SECRET_TOKEN",
764
+ "cid" => "Chat ID",
765
+ "wplc_extra_data" => "Data array"
766
+ );
767
  }
768
  } else {
769
  $return_array['response'] = "Nonce is invalid";
790
  return $return_array;
791
  }
792
 
793
+ function wplc_api_agent_is_typing_mrg(WP_REST_Request $request) {
794
+
795
+ $return_array = array();
796
+ if (isset($request)) {
797
+ if (isset($request['security'])) {
798
+ $check_token = get_option('wplc_api_secret_token');
799
+ if ($check_token !== false && $request['security'] === $check_token) {
800
+ if (isset($request['cid'])) {
801
+ if (isset($request['user'])) {
802
+ if (isset($request['type'])) {
803
+ if (wplc_typing_mrg($request['user'], sanitize_text_field($request['cid']), sanitize_text_field($request['type']))) {
804
+
805
+ $return_array['response'] = "Successful";
806
+ $return_array['code'] = "200";
807
+ $return_array['data'] = array(
808
+ "cid" => intval($request['cid']),
809
+ "user" => intval($request['user']),
810
+ "type" => intval($request['type'])
811
+ );
812
+ } else {
813
+ $return_array['response'] = "Failed to send typing indicaator";
814
+ $return_array['code'] = "401";
815
+ $return_array['requirements'] = array(
816
+ "security" => "YOUR_SECRET_TOKEN",
817
+ "cid" => "Chat ID",
818
+ "user" => "User type",
819
+ 'type' => "TYPE"
820
+ );
821
+ }
822
+ } else {
823
+
824
+ $return_array['response'] = "No 'type' found";
825
+ $return_array['code'] = "401";
826
+ $return_array['requirements'] = array(
827
+ "security" => "YOUR_SECRET_TOKEN",
828
+ "cid" => "Chat ID",
829
+ "user" => "User type",
830
+ 'type' => "TYPE"
831
+ );
832
+ }
833
+ } else {
834
+ $return_array['response'] = "No 'user' found";
835
+ $return_array['code'] = "401";
836
+ $return_array['requirements'] = array(
837
+ "security" => "YOUR_SECRET_TOKEN",
838
+ "cid" => "Chat ID",
839
+ "user" => "User type",
840
+ 'type' => "TYPE"
841
+ );
842
+ }
843
+ } else {
844
+ $return_array['response'] = "No 'cid' found";
845
+ $return_array['code'] = "401";
846
+ $return_array['requirements'] = array(
847
+ "security" => "YOUR_SECRET_TOKEN",
848
+ "cid" => "Chat ID",
849
+ "user" => "User type",
850
+ 'type' => "TYPE"
851
+ );
852
+ }
853
+ } else {
854
+ $return_array['response'] = "Nonce is invalid";
855
+ $return_array['code'] = "401";
856
+ }
857
+ } else {
858
+ $return_array['response'] = "No 'security' found";
859
+ $return_array['code'] = "401";
860
+ $return_array['requirements'] = array(
861
+ "security" => "YOUR_SECRET_TOKEN",
862
+ "cid" => "Chat ID",
863
+ "user" => "User type",
864
+ 'type' => "TYPE"
865
+ );
866
+ }
867
+ } else {
868
+ $return_array['response'] = "No request data found";
869
+ $return_array['code'] = "400";
870
+ $return_array['requirements'] = array(
871
+ "security" => "YOUR_SECRET_TOKEN",
872
+ "cid" => "Chat ID",
873
+ "user" => "User type",
874
+ 'type' => "TYPE"
875
+ );
876
+ }
877
+
878
+ return $return_array;
879
  }
880
 
881
 
882
  function wplc_api_record_agent_chat_msg_mrg($from, $cid, $msg, $rest_check = false, $ato = false, $other = false, $orig_override = false) {
883
+ global $wpdb;
884
+ global $wplc_tblname_msgs;
885
 
886
 
887
+
888
+ if (!filter_var($cid, FILTER_VALIDATE_INT)) {
 
 
 
 
 
 
889
 
890
  /**
891
+ * We need to identify if this CID is a node CID, and if so, return the WP CID from the wplc_chat_msgs table
 
 
892
  */
893
+ $cid = wplc_return_chat_id_by_rel($cid);
894
+ }
895
+
896
+ /**
897
+ * check if this CID even exists, if not, create it
898
+ *
899
+ * If it doesnt exist, it most likely is an agent-to-agent chat that we now need to save.
900
+ */
901
+
902
+ global $wplc_tblname_chats;
903
+ $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wplc_tblname_chats WHERE `rel` = %s OR `id` = %s LIMIT 1", $cid, $cid));
904
+ if (!$results) {
905
+ /* it doesnt exist, lets put it in the table */
906
+
907
+ $wpdb->insert(
908
+ $wplc_tblname_chats,
909
+ array(
910
+ 'status' => 3,
911
+ 'timestamp' => current_time('mysql'),
912
+ 'name' => 'agent-to-agent chat',
913
+ 'email' => 'none',
914
+ 'session' => '1',
915
+ 'ip' => wplc_get_user_ip(),
916
+ 'url' => '',
917
+ 'last_active_timestamp' => current_time('mysql'),
918
+ 'other' => '',
919
+ 'rel' => $cid,
920
+ ),
921
+ array(
922
+ '%s',
923
+ '%s',
924
+ '%s',
925
+ '%s',
926
+ '%s',
927
+ '%s',
928
+ '%s',
929
+ '%s',
930
+ '%s',
931
+ '%s'
932
+ )
933
+ );
934
 
 
 
 
 
 
 
 
 
935
 
936
+ $cid = $wpdb->insert_id;
937
+ }
938
+
939
+ $msg_id = '';
940
+ if ($other !== false) {
941
+ if (!empty($other->msgID)) {
942
+ $msg_id = $other->msgID;
943
  } else {
944
+ $msg_id = '';
 
 
 
 
945
  }
946
+ }
947
 
948
+ $user_info = get_userdata($from);
949
+ if ($user_info) {
950
+ $fromname = $user_info->display_name;
951
+ } else {
952
+ $fromname = 'agent';
953
+ }
954
+ $orig = '1';
955
+ if ($orig_override !== false) {
956
+ $orig = sanitize_text_field($orig_override);
957
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
958
 
959
+ $orig_msg = $msg;
960
+
961
+ $msg = apply_filters("wplc_filter_message_control", $msg);
962
+
963
+
964
+ $wpdb->insert(
965
+ $wplc_tblname_msgs,
966
+ array(
967
+ 'chat_sess_id' => $cid,
968
+ 'timestamp' => current_time('mysql'),
969
+ 'msgfrom' => $fromname,
970
+ 'msg' => $msg,
971
+ 'status' => 0,
972
+ 'originates' => $orig,
973
+ 'other' => '',
974
+ 'rel' => $msg_id,
975
+ 'ato' => $ato,
976
+ 'afrom' => $from
977
+ ),
978
+ array(
979
+ '%s',
980
+ '%s',
981
+ '%s',
982
+ '%s',
983
+ '%d',
984
+ '%s',
985
+ '%s',
986
+ '%s',
987
+ '%d',
988
+ '%d'
989
+ )
990
+ );
991
+
992
+ $data = array(
993
+ 'cid' => $cid,
994
+ 'from' => $from,
995
+ 'msg' => $orig_msg,
996
+ 'orig' => $orig
997
+ );
998
+ //do_action("wplc_hook_message_sent",$data);
999
+
1000
+ wplc_update_active_timestamp(sanitize_text_field($cid));
1001
+
1002
+
1003
+ return true;
1004
  }
1005
 
1006
  add_filter("wplc_api_remote_upload_filter", "wplc_api_agent_remote_upload_handler_mrg", 10, 2);
1007
  /*
1008
  * Processes remote uploads, from app or main agent files as an example
1009
  */
1010
+ function wplc_api_agent_remote_upload_handler_mrg($return_array, $request) {
1011
  $remote_files = $request->get_file_params();
1012
  if (is_array($remote_files)) {
1013
  $upload_dir = wp_upload_dir();
1014
  $user_dirname = $upload_dir['basedir'];
1015
+ $cid = 0;
1016
  if (isset($request['cid'])) {
1017
  $cid = sanitize_text_field($request['cid']);
1018
  if (!filter_var($cid, FILTER_VALIDATE_INT)) {
1022
  $cid = intval($cid);
1023
  }
1024
 
1025
+ if (!file_exists($user_dirname . "/wp_live_chat/")) {
1026
+ @mkdir($user_dirname . '/wp_live_chat/');
1027
+ }
1028
 
1029
+ if (!realpath($user_dirname . "/wp_live_chat/" . $cid)) {
1030
+ @mkdir($user_dirname . '/wp_live_chat/' . $cid);
1031
+ }
1032
 
1033
  if (isset($remote_files['file'])) {
1034
+ $file_name = strtolower(sanitize_file_name($remote_files['file']['name']));
1035
  $file_name = basename($file_name); //This prevents traversal
1036
  $file_name = str_replace(" ", "_", $file_name);
1037
  if (wplc_check_file_name_for_safe_extension($file_name)) {
1038
+ if (realpath($user_dirname . "/wp_live_chat/" . $cid . "/" . $file_name) == false) {
1039
  $file_name = rand(0, 10) . "-" . $file_name;
1040
+ }
1041
+ if (move_uploaded_file($remote_files['file']['tmp_name'], $user_dirname . "/wp_live_chat/" . $cid . "/" . $file_name)) {
1042
+ $response = $upload_dir['baseurl'] . "/wp_live_chat/" . $cid . "/" . $file_name;
1043
  $return_array['response'] = wp_filter_post_kses(strip_tags($response));
1044
  } else {
1045
  $return_array['response'] = __('Upload error', 'wp-live-chat-support');
1058
 
1059
  /**
1060
  * Cleanup all REST Params
1061
+ */
1062
+ function wplc_api_agent_sanitize_request_params(WP_REST_Request $request) {
1063
+ global $wpdb;
1064
+
1065
+ $params = $request->get_params();
1066
+ foreach ($params as $key => $value) {
1067
+ if (is_string($value)) {
1068
+ $request->set_param($key, $wpdb->_real_escape($value));
1069
+ }
1070
+ }
1071
 
1072
+ return $request;
1073
  }
modules/api/agent/wplc-api.php CHANGED
@@ -3,8 +3,8 @@ if ( ! defined( 'ABSPATH' ) ) {
3
  exit;
4
  }
5
 
6
- if(class_exists("WP_REST_Request")){
7
- if(current_user_can('wplc_ma_agent')) {
8
  include_once "wplc-api-routes.php";
9
  include_once "wplc-api-functions.php";
10
  }
3
  exit;
4
  }
5
 
6
+ if (class_exists("WP_REST_Request")) {
7
+ if (wplc_user_is_agent()) {
8
  include_once "wplc-api-routes.php";
9
  include_once "wplc-api-functions.php";
10
  }
modules/gdpr.php CHANGED
@@ -590,47 +590,6 @@ function wplc_gdpr_footer_mod( $footer_text ) {
590
 
591
  }
592
 
593
- add_filter( 'wplc_node_server_us_options_enabled', 'wplc_gdpr_allow_us_servers_check',10 ,2);
594
- /**
595
- * Checks if GDPR option is enabled so we can force users into the EU
596
- */
597
- function wplc_gdpr_allow_us_servers_check($is_allowed, $wplc_settings = false){
598
- if($wplc_settings === false){ $wplc_settings = wplc_get_options(); }
599
-
600
- if(isset($wplc_settings['wplc_gdpr_enabled']) && $wplc_settings['wplc_gdpr_enabled'] == '1'){
601
- return false;
602
- }
603
-
604
- return $is_allowed;
605
- }
606
-
607
-
608
- add_filter( 'wplc_node_server_default_selection_override', 'wplc_gdpr_node_server_eu_default_override',10,2);
609
- /**
610
- * Checks if GDPR option is enabled so we can force users into the EU
611
- */
612
- function wplc_gdpr_node_server_eu_default_override($selected, $wplc_settings = false){
613
- if($wplc_settings === false){ $wplc_settings = wplc_get_options(); }
614
- if(isset($wplc_settings['wplc_gdpr_enabled']) && $wplc_settings['wplc_gdpr_enabled'] == '1'){
615
- if($selected === 'auto' || substr($selected,0,2) == 'us') {
616
- //This is not allowed in the GDPR
617
- $selected = 'eu'.rand(1,10);
618
- }
619
- }
620
- return $selected;
621
- }
622
-
623
-
624
- add_action('wplc_node_server_selection_notices', 'wplc_gdpr_node_server_override_notice',10,1);
625
- /**
626
- * Will add a very simple server override if GDPR is enabled
627
- */
628
- function wplc_gdpr_node_server_override_notice($wplc_settings = false){
629
- if($wplc_settings === false){ $wplc_settings = wplc_get_options(); }
630
- if(isset($wplc_settings['wplc_gdpr_enabled']) && $wplc_settings['wplc_gdpr_enabled'] == '1'){
631
- echo "<small><strong><em>" . __("GDPR Compliance Enabled - Server Selection Limited to EU", 'wp-live-chat-support') . "</em></strong></small>";
632
- }
633
- }
634
 
635
  add_filter('wplc_update_settings_between_versions_hook', 'wplc_gdpr_update_settings_between_versions',10,1);
636
  /**
590
 
591
  }
592
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
 
594
  add_filter('wplc_update_settings_between_versions_hook', 'wplc_gdpr_update_settings_between_versions',10,1);
595
  /**
modules/node_server.php CHANGED
@@ -3,7 +3,7 @@
3
  * Node Code
4
  */
5
 
6
- if ( ! defined( 'ABSPATH' ) ) {
7
  exit;
8
  }
9
 
@@ -18,14 +18,14 @@ add_action("wplc_update_hook", "wplc_node_server_token_get", 10);
18
  * If not create one for use in the API
19
  *
20
  * @return void
21
- */
22
- function wplc_node_server_token_get($reset=false) {
23
- $tk='';
24
  if (!$reset) {
25
  $tk = get_option("wplc_node_server_secret_token");
26
  }
27
- if (empty($tk)) {
28
- $tk = wplc_node_server_token_create();
29
  update_option("wplc_node_server_secret_token", $tk);
30
  }
31
  return $tk;
@@ -35,69 +35,72 @@ add_action("wplc_admin_dashboard_render", "wplc_admin_dashboard");
35
  function wplc_admin_dashboard() {
36
  $wplc_node_token = wplc_node_server_token_get();
37
  $variables = array("node_token" => $wplc_node_token, "action" => "wordpress");
38
- $variables = apply_filters("wplc_admin_dashboard_layout_node_request_variable_filter", $variables);
39
  $wplc_settings = wplc_get_options();
40
- $status = wplc_get_agent_status(get_current_user_id());
41
- ?>
42
- <div class='nifty_top_wrapper'>
43
- <div class="wrap">
44
- <div class='floating-right-toolbar'>
45
- <label for="user_list_mobile_control" style="margin-bottom: 0;"><i id="toolbar-item-user_list" class="fa fa-bars fa-fw" title="<?php _e('Toggle user list','wp-live-chat-support');?>"></i></label>
46
- <i id="toolbar-item-fullscreen-wp" class="fa fa-clone fa-fw" title="<?php _e('Toggle WordPress Menu for a full screen experience','wp-live-chat-support');?>."></i>
47
- </div>
48
- <div id="page-wrapper" style='position:relative;'>
49
- <div class='nifty_bg_holder'>
50
- <div class='nifty_bg_holder_text'><img src='<?php echo WPLC_PLUGIN_URL;?>images/wplc_loading.png' width='50' /><br /><br /><div id='nifty_bg_holder_text_inner'>Connecting...</div></div>
51
- <div class='tcx_tips_hints'></div>
52
  </div>
53
-
 
 
 
 
 
 
 
54
  <div class="nifty_admin_overlay" style="display:none">
55
 
56
  </div>
57
-
58
- <div class="nifty_admin_chat_prompt" style="display:none">
59
- <div class="nifty_admin_chat_prompt_title" id='nifty_admin_chat_prompt_title'><?php _e('Please Confirm','wp-live-chat-support');?></div>
60
- <div class="nifty_admin_chat_prompt_message"></div>
61
- <div class="nifty_admin_chat_prompt_actions">
62
- <button class="btn btn-info" id="nifty_admin_chat_prompt_confirm"><?php _e('Confirm','wp-live-chat-support');?></button>
63
- <button class="btn btn-secondary" id="nifty_admin_chat_prompt_cancel"><?php _e('Cancel','wp-live-chat-support');?></button>
64
- </div>
65
  </div>
66
 
67
  <div id='nifty_wrapper'>
68
  <input type="checkbox" id="user_list_mobile_control" name="user_list_mobile_control" checked="checked">
69
  <div id='user_list' class='col-md-3'>
70
- <?php if ($wplc_settings['wplc_allow_agents_set_status'] && !empty($variables['aid'])) { ?>
71
  <div id='choose_online'>
72
- <div id="wplc_agent_status_text" style="display: inline-block; padding-left: 10px;"></div>
73
- <input type="checkbox" class="wplc_switchery" name="wplc_agent_status" id="wplc_agent_status"<?php echo ($status ? ' checked' : ''); ?> />
74
- </div>
75
- <?php } ?>
76
- <div id='user_count'>
77
- <span id='active_count'>... </span>
78
- <span id='active_count_string'><?php _e('Active visitors','wp-live-chat-support');?></span>
79
- </div>
80
- <div class='exp_cols'>
81
- <div class='col1'><?php _e('Name','wp-live-chat-support');?></div>
82
- <div class='col3'><?php _e('Agent','wp-live-chat-support');?></div>
83
- </div>
84
- <div class='userListBox_Wrapper'>
85
- <div class='userListBox'></div>
86
- </div>
87
- <div id='agent_list'>
88
- <h4 id='nifty_agent_heading'><?php _e('Agents','wp-live-chat-support');?></h4>
89
- <ul class='online_agent_list'>
90
- </ul>
91
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  </div>
93
 
94
  <div id='chat_area' class='col-md-9'>
95
- <?php if ($variables['include_media_sharing']){ ?>
96
- <div id="chat_drag_zone" style="display:none;"><div id="chat_drag_zone_inner"><span id='drag_zone_inner_text'><?php _e('Drag Files Here','wp-live-chat-support');?></span></div></div>
 
 
97
  <?php } ?>
98
  <div class="chatArea" style='display:none;'>
99
  <div class="chatInfoArea">
100
- <span class="minChat btn" id="tcx_min_chat" title="<?php _e('Minimize Chat','wp-live-chat-support');?>"><i class="fas fa-window-close"></i></span>
101
  <div class="dropdown pull-right"></div>
102
 
103
  <div class="btn-group inchat-menu pull-right">
@@ -107,13 +110,13 @@ function wplc_admin_dashboard() {
107
  </button>
108
  <div class="dropdown-menu" aria-labelledby='inchat_drop_down'>
109
  <?php if ($variables['include_transfers']) { ?>
110
- <a href="javascript:void(0);" class='dropdown-item chatTransfer' id='chatTransferLink'><?php _e('Invite Agent','wp-live-chat-support');?></a>
111
- <a href="javascript:void(0);" class='dropdown-item chatTransferDepartment' id='chatTransferDepLink'><?php _e('Invite Department','wp-live-chat-support');?></a>
112
- <a href="javascript:void(0);" class='dropdown-item chatDirectUserToPagePrompt' id='chatDirectUserToPageLink'><?php _e('Direct User To Page','wp-live-chat-support');?></a>
113
  <?php } ?>
114
- <a href="javascript:void(0);" class='dropdown-item chatTranscript' id='chatTranscriptTitle' style='display:none;'><?php _e('Transcript','wp-live-chat-support');?></a>
115
- <a href="javascript:void(0);" class='dropdown-item chatClose' id='chatCloseTitle' style="display:none;"><?php _e('Leave chat','wp-live-chat-support');?></a>
116
- <a href="javascript:void(0);" class='dropdown-item endChat' id='chatEndTitle'><?php _e('End chat','wp-live-chat-support');?></a>
117
  </div>
118
  </div>
119
 
@@ -122,168 +125,168 @@ function wplc_admin_dashboard() {
122
  <div class='user_gravatar'></div>
123
  </div>
124
  <div class='user_header_wrapper_info'>
125
- <h3><span class='chatInfoArea-Name'><?php _e('Name','wp-live-chat-support');?></span></h3>
126
- <h4><span class='chatInfoArea-Email'><?php _e('Email','wp-live-chat-support');?></span></h4>
127
- <p><span class='chatInfoArea-Info1'><?php _e('Something','wp-live-chat-support');?></span></p>
128
  </div>
129
-
130
  </div>
131
 
132
  <ul class="messages" id="messages"></ul>
133
-
134
- <?php if ($variables['include_quick_responses']){ ?>
135
- <div id="quick_response_drawer_handle"><i class="fa fa-bolt" title="<?php _e('Quick Responses','wp-live-chat-support');?>"></i></div>
136
  <?php } ?>
137
  <div class='typing_preview_wplc' style='display:none;'></div>
138
- <div class='tcx_join_chat_div'><button class='tcx_join_chat_btn btn btn-success' id='nifty_join_chat_button'><?php _e('Join chat','wp-live-chat-support');?></button></div>
139
- <input class="inputMessage wdt-emoji-bundle-enabled" id="inputMessage" placeholder="<?php _e('Type here...','wp-live-chat-support');?>"/>
140
- <span class="editing_hints"><strong>*<?php _e('bold','wp-live-chat-support');?>*</strong> <em>_<?php _e('italics','wp-live-chat-support');?>_</em> <code>`<?php _e('code','wp-live-chat-support');?>`</code> <code>```<?php _e('preformatted','wp-live-chat-support');?>```</code></span>
141
- <img id="wplc_send_msg" class='nifty_send_arrow' style="display:none;" src='<?php echo WPLC_PLUGIN_URL;?>images/arrow.png' />
142
-
143
- <?php if ($variables['include_media_sharing']){ ?>
144
- <label for="nifty_file_input" class='nifty_add_media_button'>
145
- <i class="nifty_tedit_icon fa fa-paperclip" id="nifty_attach" ></i>
146
- <i class="nifty_attach_icon far fa-circle-notch fa-spin" id="nifty_attach_uploading_icon" style="display:none;"></i>
147
- <i class="nifty_attach_icon fa fa-check-circle" id="nifty_attach_success_icon" style="display:none;"></i>
148
- <i class="nifty_attach_icon fa fa-minus-circle" id="nifty_attach_fail_icon" style="display:none;"></i>
149
- </label>
150
-
151
- <input type="file" id="nifty_file_input" name="nifty_file_input" style="display:none">
152
- <?php } else { ?>
153
- <label for='nifty_add_media' class="nifty_add_media_button"><i class="fa fa-plus"></i></label>
154
- <input type="checkbox" id="nifty_add_media" />
155
- <?php } ?>
156
 
157
  </div>
158
  <div class="infoArea">
159
  <div class="dropdown filter-menu pull-right">
160
- <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" style='margin-right:25px;' title="<?php _e('Filter the user list based on activity.','wp-live-chat-support');?>" id='nifty_filter_button'>
161
- Filters
162
- <span class="caret"></span>
163
- </button>
164
- <div class="dropdown-menu">
165
- <a href="javascript:void(0);" class='dropdown-item filter-new-visitors' id='nifty_new_visitor_item'><?php _e('New Visitors (3 Min)','wp-live-chat-support');?></a>
166
- <a href="javascript:void(0);" class='dropdown-item filter-active-chats' id='nifty_active_chats_item'><?php _e('Active Chats','wp-live-chat-support');?></a>
167
- <a href="javascript:void(0);" class="dropdown-item filter-referer" id="nifty_referer_item"><?php _e('Page URL','wp-live-chat-support');?></a>
168
- <a href="javascript:void(0);" class='dropdown-item filter-clear' id='nifty_clear_filters_item'><?php _e('Clear Filters','wp-live-chat-support');?></a>
169
- </div>
170
- <div class='filter-active-tag-container' style='display:none;'>
171
- <i class='fa fa-times-circle filter-clear' style="cursor:pointer;"></i>
172
- <span class='filter-active-tag-inner'></span>
173
- </div>
174
  </div>
175
 
176
- <div id="nifty_referer_options" style="display:none;float:right;margin-right:10px;">
177
- <input placeholder="Page URL" type="text" id="nifty_referer_url" style="width:100%;float:right;">
178
- <label style="font-weight:normal;">
179
- <input type="checkbox" id="nifty_referer_contains" style="margin:0;"> <?php _e('Contains','wp-live-chat-support');?>
180
- </label>
181
- </div>
 
 
182
 
183
- <h2 id='nifty_active_chats_heading'><?php _e('Active visitors','wp-live-chat-support');?></h2>
184
-
185
  <div class='visitorListBoxHeader'>
186
- <div class='vcol visCol' id='nifty_vis_col_heading'><?php _e('Visitor','wp-live-chat-support');?></div>
187
- <div class='vcol visStatusCol' id='nifty_vis_info_heading'><?php _e('Info','wp-live-chat-support');?></div>
188
- <div class='vcol visPageCol' id='nifty_vis_page_heading'><?php _e('Page','wp-live-chat-support');?></div>
189
- <div class='vcol visChatStatusCol' id='nifty_vis_status_heading'><?php _e('Chat Status','wp-live-chat-support');?></div>
190
- <?php if ($variables['include_departments']){ ?>
191
- <div class='vcol visChatDepCol' id='nifty_vis_dep_heading'><?php _e('Department','wp-live-chat-support');?></div>
192
  <?php } ?>
193
  <div class='vcol visActionCol'></div>
194
  </div>
195
- <?php if ( $wplc_settings["wplc_settings_enabled"] == 1 ) { ?>
196
- <div class='visitorListBox'>
197
-
198
- </div>
199
- <?php } ?>
200
-
201
  </div>
202
  </div>
203
- </div>
204
- <div class="wdt-emoji-popup">
205
- <a href="#" class="wdt-emoji-popup-mobile-closer"> &times; </a>
206
- <div class="wdt-emoji-menu-content">
207
- <div id="wdt-emoji-menu-header">
208
- <a class="wdt-emoji-tab" data-group-name="People"></a>
209
- <a class="wdt-emoji-tab" data-group-name="Nature"></a>
210
- <a class="wdt-emoji-tab" data-group-name="Foods"></a>
211
- <a class="wdt-emoji-tab" data-group-name="Activity"></a>
212
- <a class="wdt-emoji-tab" data-group-name="Places"></a>
213
- <a class="wdt-emoji-tab" data-group-name="Objects"></a>
214
- <a class="wdt-emoji-tab" data-group-name="Symbols"></a>
215
- <a class="wdt-emoji-tab" data-group-name="Flags"></a>
216
- </div>
217
- <div class="wdt-emoji-scroll-wrapper">
218
- <div id="wdt-emoji-menu-items">
219
- <input id="wdt-emoji-search" type="text" placeholder="<?php _e('Search','wp-live-chat-support');?>">
220
- <h3 id="wdt-emoji-search-result-title"><?php _e('Search Results','wp-live-chat-support');?></h3>
221
- <div class="wdt-emoji-sections"></div>
222
- <div id="wdt-emoji-no-result"><?php _e('No emoji found','wp-live-chat-support');?></div>
223
- </div>
224
  </div>
225
- <div id="wdt-emoji-footer">
226
- <div id="wdt-emoji-preview">
227
- <span id="wdt-emoji-preview-img"></span>
228
- <div id="wdt-emoji-preview-text">
229
- <span id="wdt-emoji-preview-name"></span><br>
230
- <span id="wdt-emoji-preview-aliases"></span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  </div>
232
  </div>
233
- <div id="wdt-emoji-preview-bundle">
234
- <span></span>
235
- </div>
236
- <span class="wdt-credit">WDT Emoji Bundle</span>
237
  </div>
 
 
 
 
 
 
 
238
  </div>
239
  </div>
 
 
240
 
241
- <script>
242
- jQuery(document).ready(function(){
243
- jQuery("#wplc_footer_loading_icon").hide();
244
- jQuery("#wplc_footer_message").fadeIn();
245
- });
246
- </script>
247
- </div>
248
- </div>
249
- <?php
250
- }
 
251
 
252
- /**
253
- * Generates a new Secret Token
254
- *
255
- * @return string
256
- */
257
- function wplc_node_server_token_create(){
258
- $the_code = rand(0, 1000) . rand(0, 1000) . rand(0, 1000) . rand(0, 1000) . rand(0, 1000);
259
- $the_time = time();
260
- $token = md5($the_code . $the_time);
261
- return $token;
262
- }
263
-
264
- /**
265
- * Post to the NODE server -
266
- *
267
- * @param string $route Route you would like to use for the node server
268
- * @param string $form_data data to send
269
- * @return string (or false on fail)
270
- */
271
- function wplc_node_server_post($route, $form_data){
272
 
273
  $url = trailingslashit(WPLC_CHAT_SERVER) . trailingslashit(tcx_NODE_END_POINTS_ROUTE) . $route;
274
 
275
- if(!isset($form_data['token'])){
276
- $form_data['token'] = tcx_NODE_END_POINT_TOKEN; //Add the security token
277
  }
278
 
279
- if(!isset($form_data['api_key'])){
280
- $form_data['api_key'] = wplc_node_server_token_get(); //Add the security token
281
  }
282
 
283
- if(!isset($form_data['origin_url'])){
284
- $ajax_url = admin_url('admin-ajax.php');
285
- $origin_url = str_replace("/wp-admin/admin-ajax.php", "", $ajax_url);
286
- $form_data['origin_url'] = $origin_url; //Add the security token
287
  }
288
 
289
  // $options = array();
@@ -291,441 +294,283 @@ function wplc_node_server_post($route, $form_data){
291
  // $result = @file_get_contents($url . "?" . http_build_query($form_data), false, $context);
292
 
293
  $result = wp_remote_get($url . "?" . http_build_query($form_data));
294
- if ( is_array( $result ) ) {
295
  $result = $result['body']; // use the content
296
  }
297
 
298
  if ($result === FALSE) {
299
- return false;
300
  } else {
301
- return $result;
302
- }
303
- }
304
-
305
- add_action("wplc_api_route_hook", "wplc_api_node_routes");
306
- /**
307
- * Add a REST API routes for the node server
308
- *
309
- * @return void
310
- */
311
- function wplc_api_node_routes(){
312
- register_rest_route('wp_live_chat_support/v1','/async_storage', array(
313
- 'methods' => 'POST',
314
- 'callback' => 'wplc_node_async_storage_rest'
315
- ));
316
- }
317
-
318
- /**
319
- * Handles Async storage REST -> Params are processed within the request
320
- * Required POST variables:
321
- * - Chat ID
322
- * - Security Key
323
- * - Message (JSON encoded array)
324
- * - Action
325
- *
326
- * @param WP_REST_Request $request Request Data
327
- * @return void
328
- */
329
- function wplc_node_async_storage_rest(WP_REST_Request $request){
330
-
331
- $return_array = array();
332
- $return_array['request_status'] = false; //Default to be returned if something goes wrong
333
- if(isset($request)){
334
- if(isset($request['security'])){
335
- $stored_token = wplc_node_server_token_get();
336
- $check = $_POST['server_token'] == $stored_token ? true : false;
337
- if ($check) {
338
- if(isset($request['chat_id'])){
339
- if(isset($request['messages'])){
340
- if(isset($request['relay_action'])){
341
- $chat_id = sanitize_text_field($request['chat_id']);
342
- $message_data = json_decode($request['messages']);
343
- $chat_session = wplc_return_chat_session_variable($chat_id);
344
- $action = $request['relay_action'];
345
- if($message_data !== NULL){
346
- if($action == "wplc_user_send_msg"){
347
- foreach ($message_data as $message) {
348
- wplc_record_chat_msg("1", $chat_id, $message);
349
- wplc_update_active_timestamp($chat_id);
350
- }
351
-
352
- $return_array['request_status'] = true;
353
- $return_array['request_information'] = __("Success", 'wp-live-chat-support');
354
- } else if ($action == "wplc_admin_send_msg"){
355
- foreach ($message_data as $message) {
356
- wplc_record_chat_msg("2", $chat_id, $message, true);
357
- wplc_update_active_timestamp($chat_id);
358
- }
359
-
360
- $return_array['request_status'] = true;
361
- $return_array['request_information'] = __("Success", 'wp-live-chat-support');
362
- }
363
- } else {
364
- $return_array['request_information'] = __("Message data is corrupt", 'wp-live-chat-support');
365
- }
366
- } else {
367
- $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
368
- }
369
- } else {
370
- $return_array['request_information'] = __("Message data array not set", 'wp-live-chat-support');
371
- }
372
- } else {
373
- $return_array['request_information'] = __("Chat ID is not set", 'wp-live-chat-support');
374
- }
375
- }
376
- } else {
377
- $return_array['request_information'] = __("No security nonce found", 'wp-live-chat-support');
378
- }
379
- }
380
-
381
- return $return_array;
382
-
383
- }
384
-
385
- add_action("wp_ajax_wplc_node_async_storage_ajax", "wplc_node_async_storage_ajax");
386
- add_action("wp_ajax_nopriv_wplc_node_async_storage_ajax", "wplc_node_async_storage_ajax");
387
- /**
388
- * Handles Async storage AJAX (Fallback for if REST is not present) -> Params are processed within the request
389
- * Required POST variables:
390
- * - Chat ID
391
- * - Security Key
392
- * - Message (JSON encoded array)
393
- * - Action
394
- *
395
- * @return void
396
- */
397
- function wplc_node_async_storage_ajax(){
398
- $return_array = array();
399
- $return_array['request_status'] = false; //Default to be returned if something goes wrong
400
- if(isset($_POST)){
401
- if(isset($_POST['server_token'])){
402
- $stored_token = wplc_node_server_token_get();
403
- $check = $_POST['server_token'] == $stored_token ? true : false;
404
- if ($check) {
405
- if(isset($_POST['chat_id'])){
406
- if(isset($_POST['messages'])){
407
- if(isset($_POST['relay_action'])){
408
- $chat_id = sanitize_text_field($_POST['chat_id']);
409
- $message_data = json_decode($_POST['messages']);
410
- $chat_session = wplc_return_chat_session_variable($chat_id);
411
- $action = sanitize_text_field($_POST['relay_action']);
412
- if($message_data !== NULL){
413
- if($action == "wplc_user_send_msg"){
414
- foreach ($message_data as $message) {
415
- wplc_record_chat_msg("1", $chat_id, $message);
416
- wplc_update_active_timestamp($chat_id);
417
-
418
- }
419
-
420
- $return_array['request_status'] = true;
421
- $return_array['request_information'] = __("Success", 'wp-live-chat-support');
422
- } else if ($action == "wplc_admin_send_msg"){
423
- foreach ($message_data as $message) {
424
- wplc_record_chat_msg("2", $chat_id, $message);
425
- wplc_update_active_timestamp($chat_id);
426
- }
427
-
428
- $return_array['request_status'] = true;
429
- $return_array['request_information'] = __("Success", 'wp-live-chat-support');
430
- }
431
- } else {
432
- $return_array['request_information'] = __("Message data is corrupt", 'wp-live-chat-support');
433
- }
434
- } else {
435
- $return_array['request_information'] = __("Action not set", 'wp-live-chat-support');
436
- }
437
- } else {
438
- $return_array['request_information'] = __("Message data array not set", 'wp-live-chat-support');
439
- }
440
- } else {
441
- $return_array['request_information'] = __("Chat ID is not set", 'wp-live-chat-support');
442
- }
443
- }
444
- } else {
445
- $return_array['request_information'] = __("No security nonce found", 'wp-live-chat-support');
446
- }
447
- }
448
-
449
- return $return_array;
450
-
451
- }
452
-
453
- /**
454
- * Loads remote dashboard
455
- *
456
- * @return void
457
- */
458
- function wplc_admin_dashboard_layout_node( $location = 'dashboard' ) {
459
- if ($location == 'dashboard') {
460
- if (!get_user_meta(get_current_user_id(), 'wplc_ma_agent', true)) {
461
- echo "<div class='error below-h1'><h2>".__("Error", 'wp-live-chat-support')."</h2><p>".__("Only chat agents can access this page.", 'wp-live-chat-support')."</p></div>";
462
- return;
463
  }
464
  }
465
- do_action("wplc_admin_remote_dashboard_above");
466
- echo "<div id='tcx_content_wrapper'></div>";
467
- if ($location == 'dashboard') {
468
- if ( ! isset( $_GET['action'] ) || 'history' !== $_GET['action'] ) {
469
- echo "<div class='wplc_remote_dash_below_contianer'>";
470
- do_action("wplc_admin_dashboard_render");
471
- do_action("wplc_admin_remote_dashboard_below");
472
- echo "</div>";
 
 
 
 
473
  }
474
- } else {
475
- if ( ! empty( $_GET['page'] ) && 'wplivechat-menu' === $_GET['page'] ) { // This div is also hidden by js under the same conditions
476
- echo "<div class='wplc_remote_dash_below_contianer'>";
477
- do_action("wplc_admin_remote_dashboard_below");
478
- do_action("wplc_admin_dashboard_render");
479
- echo "</div>";
 
 
 
480
  } else {
481
- $wplc_settings = wplc_get_options();
482
- if ($wplc_settings['wplc_use_node_server']) {
483
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'wplivechat-menu') {
484
- } else {
485
- if ($wplc_settings['wplc_enable_all_admin_pages']) {
486
- echo "<div class='wplc_remote_dash_below_contianer'>";
487
- do_action("wplc_admin_dashboard_render");
488
- echo "</div>";
 
 
 
 
 
 
489
  }
490
  }
491
  }
492
  }
493
  }
494
- }
495
 
496
- add_action('admin_enqueue_scripts', 'wplc_enqueue_dashboard_popup_scripts');
497
- /**
498
- * Enqueues the scripts for the admin dashboard popup icon and chat box
499
- * @return void
500
- */
501
- function wplc_enqueue_dashboard_popup_scripts() {
502
- wp_enqueue_script('jquery-ui-draggable');
503
- wp_enqueue_script('wplc-admin-popup', WPLC_PLUGIN_URL.'/js/wplc_admin_popup.js', array('jquery-ui-draggable'), WPLC_PLUGIN_VERSION);
504
-
505
- wp_button_pointers_load_scripts('toplevel_page_wplivechat-menu');
506
- }
507
 
508
- add_action( "admin_footer", "wplc_dashboard_display_decide" );
509
- /**
510
- * Decide whether or not to display the dashboard layout on an admin page
511
- * @return void
512
- */
513
- function wplc_dashboard_display_decide() {
514
- $wplc_settings = wplc_get_options();
515
- if ($wplc_settings['wplc_use_node_server']) {
516
- //Node in use, load remote dashboard
517
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'wplivechat-menu') {
518
- } else {
519
- /**
520
- * Check to see if we have enabled "Enable chat dashboard and notifications on all admin pages"
521
- */
522
-
523
- if ($wplc_settings['wplc_enable_all_admin_pages']) {
524
- wplc_admin_dashboard_layout_node('other');
525
- echo '<div class="floating-right-toolbar">';
526
- echo '<label for="user_list_tcx_control" style="margin-bottom: 0; display:none;"></label>';
527
- echo '<i id="toolbar-item-open-tcx" class="fa fa-fw" style="background:url(\''.plugins_url('../images/tcx48px.png', __FILE__).'\') no-repeat; background-size: cover;"></i>';
528
- echo '</div>';
 
 
 
529
  }
530
  }
531
  }
532
- }
533
 
534
- /**
535
- * Loads remote dashboard scripts and styles
536
- *
537
- * @return void
538
- */
539
- function wplc_admin_remote_dashboard_scripts($wplc_settings){
540
- $wplc_current_user = get_current_user_id();
541
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true )) {
542
-
543
- $user_info = get_userdata(intval($wplc_current_user));
544
-
545
- $user_array = get_users(array(
546
- 'meta_key' => 'wplc_ma_agent',
547
- ));
548
-
549
- $a_array = array();
550
- if ($user_array) {
551
- foreach ($user_array as $user) {
552
- $a_array[$user->ID] = array();
553
- $a_array[$user->ID]['name'] = $user->display_name;
554
- $a_array[$user->ID]['display_name'] = $user->display_name;
555
- $a_array[$user->ID]['md5'] = md5( $user->user_email );
556
- $a_array[$user->ID]['email'] = md5( $user->user_email );
557
  }
558
- }
559
 
560
- wp_register_script('wplc-admin-js-sockets', WPLC_PLUGIN_URL."/js/vendor/sockets.io/socket.io.slim.js", false, WPLC_PLUGIN_VERSION, false);
561
- wp_enqueue_script('wplc-admin-js-sockets');
562
-
563
- wp_register_script('wplc-admin-js-bootstrap', WPLC_PLUGIN_URL."/js/vendor/bootstrap/dist/js/bootstrap.js", array("wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false);
564
- wp_enqueue_script('wplc-admin-js-bootstrap');
565
-
566
- wplc_register_common_node();
567
-
568
- // NB: This causes Failed to initVars ReferenceError: wplc_show_date is not defined when uncommented and enabled
569
- if (!$wplc_settings['wplc_disable_emojis']) {
570
- wp_register_script('wplc-admin-js-emoji', WPLC_PLUGIN_URL."/js/vendor/wdt-emoji/emoji.min.js", array("wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false);
571
- wp_enqueue_script('wplc-admin-js-emoji');
572
- wp_register_script('wplc-admin-js-emoji-bundle', WPLC_PLUGIN_URL."/js/vendor/wdt-emoji/wdt-emoji-bundle.min.js", array("wplc-admin-js-emoji"), WPLC_PLUGIN_VERSION, false);
573
- wp_enqueue_script('wplc-admin-js-emoji-bundle');
574
- }
575
-
576
- wp_register_script('md5', WPLC_PLUGIN_URL.'/js/md5.js', array("wplc-admin-js-sockets"), false, false);
577
- wp_enqueue_script('md5');
578
-
579
- $dependencies = array();
580
- if (!$wplc_settings['wplc_disable_emojis']) {
581
- $dependencies[] = "wplc-admin-js-emoji-bundle";
582
- }
583
- wp_register_script('wplc-admin-js-agent', WPLC_PLUGIN_URL.'/js/wplc_agent_node.js', $dependencies, WPLC_PLUGIN_VERSION, false);
584
- wp_localize_script('wplc-admin-js-agent', "tcx_ping_sound_notification_enabled", array('value'=>boolval($wplc_settings['wplc_enable_msg_sound'])));
585
-
586
- wp_register_script('my-wplc-admin-chatbox-ui-events', WPLC_PLUGIN_URL.'/js/wplc_u_admin_chatbox_ui_events.js', array('jquery'), WPLC_PLUGIN_VERSION, true);
587
- wp_enqueue_script('my-wplc-admin-chatbox-ui-events');
588
-
589
-
590
-
591
- $wplc_et_ajax_nonce = wp_create_nonce( "wplc_et_nonce" );
592
- wp_register_script( 'wplc_transcript_admin', WPLC_PLUGIN_URL.'/js/wplc_transcript.js', null, '', true );
593
- $wplc_transcript_localizations = array(
594
- 'ajax_nonce' => $wplc_et_ajax_nonce,
595
- 'string_loading' => __( "Sending transcript...", 'wp-live-chat-support'),
596
- 'string_title' => __( "Chat Transcript", 'wp-live-chat-support'),
597
- 'string_close' => __( "Close", 'wp-live-chat-support'),
598
- 'string_chat_emailed' => __( "The chat transcript has been emailed.", 'wp-live-chat-support'),
599
- 'string_error1' => __( "There was a problem emailing the chat.", 'wp-live-chat-support')
600
- );
601
- wp_localize_script( 'wplc_transcript_admin', 'wplc_transcript_nonce', $wplc_transcript_localizations );
602
- wp_enqueue_script( 'wplc_transcript_admin' );
603
-
604
- $wplc_node_token = wplc_node_server_token_get();
605
-
606
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'wplivechat-menu' ) {
607
- wp_localize_script('wplc-admin-js-agent', 'tcx_in_dashboard', array('value'=>true));
608
- } else {
609
- wp_localize_script('wplc-admin-js-agent', 'tcx_in_dashboard', array('value'=>false));
610
- }
611
-
612
- $inline_error_message = "<div class='error below-h1' style='display:none;' id='tcx_inline_connection_error'>
613
  <p>" . __("Connection Error", 'wp-live-chat-support') . "<br /></p>
614
  <p>" . __("We are having some trouble contacting the server. Please try again later.", 'wp-live-chat-support') . "</p>
615
  </div>";
616
- wp_localize_script('wplc-admin-js-agent', 'tcx_remote_form_error', $inline_error_message);
617
 
618
 
619
- wp_localize_script('wplc-admin-js-agent', 'tcx_enable_visitor_sound', array('value'=>$wplc_settings['wplc_enable_visitor_sound']));
620
 
621
- $agent_display_name = $user_info->display_name;
622
 
623
- wp_localize_script('wplc-admin-js-agent', 'agent_id', "" . $wplc_current_user);
624
- wp_localize_script('wplc-admin-js-agent', 'tcx_agent_name', apply_filters("wplc_agent_display_name_filter", $agent_display_name) );
625
- wp_localize_script('wplc-admin-js-agent', 'nifty_api_key', wplc_node_server_token_get());
626
 
627
- //For node verification
628
- wplc_check_guid();
629
 
630
- wp_localize_script('wplc-admin-js-agent', 'wplc_guid', get_option('WPLC_GUID', ''));
631
- wp_localize_script('wplc-admin-js-agent', 'tcx_agent_verification_end_point', rest_url('wp_live_chat_support/v1/validate_agent'));
632
- wp_localize_script('wplc-admin-js-agent', 'tcx_disable_add_message', array('value'=>true));
633
- wp_localize_script('wplc-admin-js-agent', 'wplc_nonce', wp_create_nonce("wplc"));
634
- wp_localize_script('wplc-admin-js-agent', 'wplc_cid', null);
635
- wp_localize_script('wplc-admin-js-agent', 'wplc_chat_name', null);
636
-
637
- $wplc_chat_detail = array(
638
- 'name' => $wplc_settings['wplc_show_name'],
639
- 'avatar' => $wplc_settings['wplc_show_avatar'],
640
- 'date' => $wplc_settings['wplc_show_date'],
641
- 'time' => $wplc_settings['wplc_show_time'],
642
- );
643
- wp_localize_script( 'wplc-admin-js-agent', 'wplc_show_chat_detail', $wplc_chat_detail);
644
- wp_localize_script('wplc-admin-chat-server', 'wplc_show_chat_detail', $wplc_chat_detail);
645
 
646
- wp_localize_script('wplc-admin-js-agent', 'wplc_agent_data', $a_array);
647
- wp_localize_script('wplc-admin-js-agent', 'all_agents', $a_array);
 
 
 
 
 
 
648
 
649
- wp_localize_script('wplc-admin-js-agent', 'wplc_url', plugins_url( '', dirname( __FILE__ ) ) );
 
650
 
651
- if( isset($wplc_settings['wplc_settings_enabled']) && intval($wplc_settings["wplc_settings_enabled"]) == 2) {
652
- $wplc_disabled_html = __("Chat is disabled in settings area, re-enable", 'wp-live-chat-support');
653
- $wplc_disabled_html .= " <a href='?page=wplivechat-menu-settings'>" . __("here", 'wp-live-chat-support') . "</a>";
654
- wp_localize_script('wplc-admin-js-agent', 'wplc_disabled', array('value'=>true));
655
- wp_localize_script('wplc-admin-js-agent', 'wplc_disabled_html', $wplc_disabled_html);
656
- } else {
657
- wp_localize_script('wplc-admin-js-agent', 'wplc_disabled', array('value'=>false));
658
- }
 
 
659
 
660
- //Added rest nonces
661
- if(class_exists("WP_REST_Request")) {
662
- wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_enabled', array('value'=>true));
663
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_token', get_option('wplc_api_secret_token'));
664
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_endpoint', rest_url('wp_live_chat_support/v1'));
665
  wp_localize_script('wplc-admin-js-agent', 'tcx_override_upload_url', rest_url('wp_live_chat_support/v1/remote_upload'));
666
- wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_nonce', wp_create_nonce( 'wp_rest' ));
667
-
668
- } else {
669
- wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_enabled', array('value'=>false));
670
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_nonce', '');
671
- }
672
 
673
- // $agent_tagline = apply_filters( "wplc_filter_simple_agent_data_agent_tagline", '', get_current_user_id() );
674
- $agent_tagline = get_user_meta( intval(get_current_user_id()), 'wplc_user_tagline', true );
675
- $head_data = array(
676
- 'tagline' => $agent_tagline
677
- );
678
- wp_localize_script( 'wplc-admin-js-agent', 'wplc_head_data', $head_data );
679
- wp_localize_script( 'wplc-admin-js-agent', 'wplc_user_chat_notification_prefix', __("User received notification:", 'wp-live-chat-support') );
680
 
681
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_valid_direct_to_page_array', wplc_node_pages_posts_array() );
682
 
683
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_ringer_count', array('value'=>intval($wplc_settings['wplc_new_chat_ringer_count'])));
684
 
685
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_new_chat_notification_title', __('New chat received', 'wp-live-chat-support') );
686
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_new_chat_notification_text', __("A new chat has been received. Please go the 'Live Chat' page to accept the chat", 'wp-live-chat-support') );
687
 
688
- $wplc_notification_icon = plugin_dir_url(dirname(__FILE__)) . 'images/wplc_notification_icon.png';
689
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_new_chat_notification_icon', $wplc_notification_icon );
690
 
691
- do_action("wplc_admin_remoter_dashboard_scripts_localizer"); //For pro localization of agents list, and departments
692
 
693
- wp_enqueue_script('wplc-admin-js-agent');
694
 
695
- wp_register_script('wplc-admin-chat-server', WPLC_PLUGIN_URL.'/js/wplc_server.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
696
- wp_enqueue_script('wplc-admin-chat-server');
697
 
698
- wp_localize_script( 'wplc-admin-chat-server', 'wplc_datetime_format', array(
699
- 'date_format' => get_option( 'date_format' ),
700
- 'time_format' => get_option( 'time_format' ),
701
- ) );
702
-
703
- wp_register_script('wplc-admin-chat-events', WPLC_PLUGIN_URL.'/js/wplc_u_admin_events.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
704
- wp_enqueue_script('wplc-admin-chat-events');
705
 
706
- }
707
- }
 
 
708
 
709
 
710
- /**
711
- * Loads remote dashboard styles
712
- *
713
- * @return void
714
- */
715
- function wplc_admin_remote_dashboard_styles(){
716
  $wplc_settings = wplc_get_options();
717
 
718
- wp_register_style( 'wplc-admin-style', WPLC_PLUGIN_URL."/css/chat_dashboard/admin_style.css", false, WPLC_PLUGIN_VERSION );
719
- wp_enqueue_style( 'wplc-admin-style' );
720
 
721
- if (!isset($wplc_settings['wplc_show_avatar']) || (isset($wplc_settings['wplc_show_avatar']) && intval($wplc_settings['wplc_show_avatar']) == 0) ) {
722
- wp_add_inline_style( 'wplc-admin-style', ".wplc-user-message, .wplc-admin-message { padding-left: 0 !important; }" );
723
-
724
- } else if( !isset($wplc_settings['wplc_show_name']) || (isset($wplc_settings['wplc_show_name']) && intval($wplc_settings['wplc_show_name']) == 0) ){
725
- //User has enabled the gravatar, but has chosen to hide the user name.
726
- //This causes some issues with admin display so let's just add some different styling to get around this
727
- $inline_identity_css =
728
- "
729
  .wplc-admin-message-avatar, .wplc-user-message-avatar {
730
  max-width:28px !important;
731
  max-height:28px !important;
@@ -751,121 +596,121 @@ function wplc_admin_remote_dashboard_styles(){
751
  }
752
  ";
753
 
754
- wp_add_inline_style( 'wplc-admin-style', $inline_identity_css );
755
  }
756
 
757
- wp_register_style( 'wplc-admin-style-bootstrap', WPLC_PLUGIN_URL."/css/bootstrap.css", false, WPLC_PLUGIN_VERSION );
758
- wp_enqueue_style( 'wplc-admin-style-bootstrap' );
759
 
760
- if (!$wplc_settings['wplc_disable_emojis']) {
761
- wp_register_style( 'wplc-admin-style-emoji', WPLC_PLUGIN_URL."/js/vendor/wdt-emoji/wdt-emoji-bundle.css", false, WPLC_PLUGIN_VERSION );
762
- wp_enqueue_style( 'wplc-admin-style-emoji' );
763
- }
764
-
765
- do_action("wplc_admin_remote_dashboard_styles_hook");
766
- }
767
 
768
- /*
 
 
 
769
  * Add action for notice checks
770
  */
771
- if ( ! function_exists( "wplc_active_chat_box_notices" ) ) {
772
- if(isset($_GET['page']) && $_GET['page'] === "wplivechat-menu"){
773
- add_action( "wplc_admin_remote_dashboard_above", "wplc_active_chat_box_notices" );
774
- }
775
- }
776
 
777
- add_action("admin_notices", "wplc_node_v8_plus_notice_dismissable");
778
- /*
779
  * Displays an admin notice (which can be dismissed), to notify any V8+ users of the node option (if not already checked)
780
  */
781
- function wplc_node_v8_plus_notice_dismissable() {
782
- $page='';
783
- if (isset($_GET['page'])){
784
- $page=preg_replace('/[^a-z0-9-]/', '', sanitize_text_field($_GET['page']));
785
- }
786
- if (!empty($page) && strpos($page, 'wplivechat') === 0) { // only if it begins with wplivechat
787
- if (isset($_GET['wplc_dismiss_notice_v8']) && $_GET['wplc_dismiss_notice_v8'] === "true") {
788
- update_option("wplc_node_v8_plus_notice_dismissed", 'true');
789
  }
790
-
791
- $wplc_settings = wplc_get_options();
792
- if (!$wplc_settings['wplc_use_node_server']) {
793
- //User is not on node, let's check if they have seen this notice before, if not, let's show a notice
794
- $wplc_has_notice_been_dismissed = get_option("wplc_node_v8_plus_notice_dismissed", false);
795
- if ($wplc_has_notice_been_dismissed === false) {
796
- //Has not been dismissed
797
- $output = "<div class='notice notice-warning' style='border-color: #0180bc;'>";
798
- $output .= "<p><strong>" . __( 'Welcome to V8 of WP Live Chat by 3CX', 'wp-live-chat-support') . "</strong></p>";
799
- $output .= "<p>" . __('Did you know, this version features high speed message delivery, agent to agent chat, and a single window layout?', 'wp-live-chat-support') . "</p>";
800
- $output .= "<p>" . __('To activate this functionality please navigate to Live Chat -> Settings -> Advanced Features -> And enable 3CX High Performance Chat Cloud Servers.', 'wp-live-chat-support') . "</p>";
801
-
802
- $output .= "<p>";
803
- $output .= "<a href='?page=wplivechat-menu-settings#tabs-beta' class='button button-primary'>" . __("Show me!", 'wp-live-chat-support') . "</a> ";
804
- $output .= "<a href='?page=".$page."&wplc_dismiss_notice_v8=true' id='wplc_v8_dismiss_node_notice' class='button'>" . __("Don't Show This Again", 'wp-live-chat-support') . "</a>";
805
- $output .= "</p>";
806
- $output .= "</div>";
807
- echo $output;
 
 
 
 
 
808
  }
809
  }
810
  }
811
- }
812
 
813
- add_filter( 'rest_url', 'wplc_node_rest_url_ssl_fix');
814
- /**
815
- * Changes the REST URL to include the SSL version if we are using SSL
816
- * See https://core.trac.wordpress.org/ticket/36451
817
- */
818
- function wplc_node_rest_url_ssl_fix($url){
819
- if (is_ssl()){
820
- $url = set_url_scheme( $url, 'https' );
821
- return $url;
822
- }
823
- return $url;
824
- }
825
 
826
- /**
827
- * Returns an array of pages/posts available on the site
828
- */
829
- function wplc_node_pages_posts_array(){
830
  $r = array(
831
- 'depth' => 0,
832
- 'child_of' => 0,
833
- 'echo' => false,
834
- 'id' => '',
835
- 'class' => '',
836
- 'show_option_none' => '',
837
- 'show_option_no_change' => '',
838
- 'option_none_value' => '',
839
- 'value_field' => 'ID',
840
  );
841
 
842
- $pages = get_pages($r);
843
- $posts = get_posts(array('posts_per_page' => -1));
844
 
845
- $posts_pages = array_merge($pages,$posts);
846
 
847
- $return_array = array();
848
 
849
- foreach ($posts_pages as $key => $value) {
850
- $post_page_id = $value->ID;
851
- $post_page_title = $value->post_title;
852
 
853
- $return_array[get_permalink($post_page_id)] = $post_page_title;
854
- }
855
 
856
- return $return_array;
857
- }
858
 
859
 
860
 
861
- add_action("wplc_admin_remoter_dashboard_scripts_localizer", "wplc_admin_remote_dashboard_dynamic_translation_handler");
862
- /*
863
  * Localizes an array of strings and ids in the dashboard which need to be replaced
864
  * Loads the custom JS file responsible for replacing the content dynamically.
865
  */
866
- function wplc_admin_remote_dashboard_dynamic_translation_handler(){
867
 
868
- wp_register_script('wplc-admin-dynamic-translation', WPLC_PLUGIN_URL.'/js/wplc_admin_dynamic_translations.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets", "jquery"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
869
 
870
  $wplc_dynamic_translation_array = array(
871
  'nifty_bg_holder_text_inner' => __('Connecting...', 'wp-live-chat-support'),
@@ -905,164 +750,164 @@ function wplc_admin_remote_dashboard_dynamic_translation_handler(){
905
 
906
  wp_localize_script('wplc-admin-dynamic-translation', 'wplc_dynamic_translation_array', $wplc_dynamic_translation_array);
907
  wp_enqueue_script('wplc-admin-dynamic-translation');
908
-
909
- }
910
 
911
 
912
 
913
 
914
- add_action("wplc_admin_remoter_dashboard_scripts_localizer", "wplc_admin_remote_dashboard_localize_variables");
915
- /*
916
  * Localizes all the admin variables
917
  */
918
- function wplc_admin_remote_dashboard_localize_variables(){
919
- $wplc_settings = wplc_get_options();
920
- $user_id = get_current_user_id();
921
- $user_department = get_user_meta($user_id ,"wplc_user_department", true);
922
- $department_array = array();
923
- $departments = wplc_get_all_deparments_mrg();
924
- if ($departments) {
925
- foreach($departments as $dep){
926
- $department_array[$dep->id] = $dep->name;
 
927
  }
928
- }
929
- $departments['any'] = __("None", 'wp-live-chat-support');
930
- $default_department = $wplc_settings['wplc_default_department'];
931
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_departments', $department_array );
932
-
933
- if ($wplc_settings['wplc_allow_department_selection'] && !empty($department_array)) {
934
- if (intval($default_department) >= 0) {
935
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_default_department_tag', $department_array[$default_department] );
 
 
936
  } else {
937
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_default_department_tag', $departments['any'] );
938
  }
939
- } else {
940
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_default_department_tag', 'any' );
941
- }
942
 
943
- if (!empty($user_department)) {
944
- wp_localize_script( 'wplc-admin-js-agent', 'tcx_agent_department', $user_department);
 
 
 
 
 
945
  }
946
- wp_register_script('wplc-admin-chat-events-pro', WPLC_PLUGIN_URL . 'js/wplc_admin_pro_events.js', array("wplc-admin-js-agent", "wplc-admin-chat-events", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
947
- wp_enqueue_script('wplc-admin-chat-events-pro');
948
- wp_register_script('wplc-admin-tcx-event-tracking-pro', WPLC_PLUGIN_URL . 'js/wplc_tcx_admin_events.js', array("wplc-admin-js-agent", "wplc-admin-chat-events", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
949
- wp_enqueue_script('wplc-admin-tcx-event-tracking-pro');
950
- }
951
 
952
- add_filter("wplc_admin_dashboard_layout_node_request_variable_filter", "wplc_admin_dashboard_layout_node_request_add_mrg_variables", 10, 1);
953
- /*
954
  * Adds the Pro request variables to our node request
955
  */
956
- function wplc_admin_dashboard_layout_node_request_add_mrg_variables($variables) {
957
- if (is_array($variables)) {
958
- $variables['include_filters'] = true;
959
- $variables['include_transfers'] = true;
960
- $variables['include_media_sharing'] = true;
961
- $variables['include_quick_responses'] = true;
962
- $variables['include_departments'] = true;
963
- $variables['aid'] = get_current_user_id();
964
- $variables['agent_count'] = wplc_maa_total_agents_online();
965
- }
966
- return $variables;
967
- }
968
 
969
- add_filter("wplc_admin_remote_dashboard_localize_tips_array", "wplc_admin_remote_dashboard_localize_tips_array_mrg_handler", 1, 1);
970
- /*
971
  * Overrides the tip array in the Pro add-on
972
  */
973
- function wplc_admin_remote_dashboard_localize_tips_array_mrg_handler($tip_array) {
974
- $tip_array = array(
975
- "0" => "<p>" . __("You can transfer chats from within a chat by clicking on the in chat menu, and selecting Transfer Chat or Transfer Department", 'wp-live-chat-support') . "</p>",
976
- "1" => "<p>" . __("You can share files quickly when in a chat, by simply dragging a file into the chat window!", 'wp-live-chat-support') . "</p>",
977
- "2" => "<p>" . __("You can now move between chats without ending/closing an open chat", 'wp-live-chat-support') . "</p>"
978
- );
979
- return $tip_array;
980
- }
981
 
982
 
983
- /**
984
- * Return a count of unread messages for a specific agent from a specific agent
985
- *
986
- * @param [intval] $ato Agent ID
987
- * @param [intval] $afrom Agent ID
988
- * @return [intval] Count
989
- */
990
- function wplc_return_unread_agent_messages_mrg( $ato = 0, $afrom = 0 ) {
991
  global $wpdb;
992
  global $wplc_tblname_msgs;
993
- $count = $wpdb->get_var( $wpdb->prepare("SELECT count(id) FROM $wplc_tblname_msgs WHERE ato = %d AND afrom = %d AND status = 0",$ato,$afrom) );
994
  return $count;
995
- }
996
 
997
- add_action("wplc_admin_remote_dashboard_above", "wplc_admin_remote_dashboard_quick_responses_container_mrg");
998
- /*
999
  * Adds the quick response container
1000
  */
1001
- function wplc_admin_remote_dashboard_quick_responses_container_mrg(){
1002
 
1003
  $wplc_settings = wplc_get_options();
1004
- $wplc_quick_response_order_by = isset( $wplc_settings['wplc_quick_response_orderby'] ) ? sanitize_text_field( $wplc_settings['wplc_quick_response_orderby'] ) : 'title';
1005
- $wplc_quick_response_order = isset( $wplc_settings['wplc_quick_response_order'] ) ? sanitize_text_field( $wplc_settings['wplc_quick_response_order'] ) : 'DESC';
1006
  $args = array(
1007
- 'posts_per_page' => -1,
1008
- 'offset' => 0,
1009
- 'category' => '',
1010
- 'order' => $wplc_quick_response_order,
1011
- 'orderby' => $wplc_quick_response_order_by != 'number' ? $wplc_quick_response_order_by : 'meta_value_num',
1012
- 'include' => '',
1013
- 'exclude' => '',
1014
- 'meta_key' => $wplc_quick_response_order_by != 'number' ? '' : 'wplc_quick_response_number',
1015
- 'meta_value' => '',
1016
- 'post_type' => 'wplc_quick_response',
1017
- 'post_mime_type' => '',
1018
- 'post_parent' => '',
1019
- 'post_status' => 'publish',
1020
- 'suppress_filters' => true);
 
1021
  $posts_array = get_posts($args);
1022
  echo '<div id="quick_response_drawer_container" style="display:none;">';
1023
- echo '<h5>'.__("Quick Responses", 'wp-live-chat-support').'</h5>';
1024
- echo '<hr>';
1025
- //Add quick responses
1026
- if($posts_array){
1027
- foreach ($posts_array as $post) {
1028
- echo '<div class="quick_response_item">'.$post->post_content.'</div>';
1029
- }
1030
  } else {
1031
- echo "<div style='position: absolute; top: 23px; bottom: 0; left: 10px; right: 0; margin: auto; height: 20px;'>";
1032
- echo __("No quick responses found", 'wp-live-chat-support') . " - <a target='_blank' href='" . admin_url('post-new.php?post_type=wplc_quick_response') . "'>" . __("Add New Quick Response", 'wp-live-chat-support') . "</a>";
1033
- echo "</div>";
1034
  }
1035
  echo '</div>';
1036
- }
1037
 
1038
 
1039
- add_filter("wplc_agent_display_name_filter", "wplc_agent_display_name_filter_control_mrg", 10, 1);
1040
- /*
1041
  * Filters the agent display name
1042
  */
1043
- function wplc_agent_display_name_filter_control_mrg($wplc_display_name) {
1044
- $wplc_settings = wplc_get_options();
1045
- if (!empty($wplc_settings['wplc_use_wp_name'])) {
1046
- return $wplc_display_name;
1047
- } else {
1048
- if (!empty($wplc_settings['wplc_chat_name'])) {
1049
- $wplc_display_name = $wplc_settings['wplc_chat_name'];
 
1050
  }
 
1051
  }
1052
- return $wplc_display_name;
1053
- }
1054
 
1055
- add_action("wplc_admin_remote_dashboard_styles_hook", "wplc_admin_remote_dashboard_styles_mrg");
1056
- /**
1057
- * Loads remote dashboard styles
1058
- *
1059
- * @return void
1060
- */
1061
- function wplc_admin_remote_dashboard_styles_mrg(){
1062
- $wplc_settings = wplc_get_options();
1063
 
1064
- if (!$wplc_settings['wplc_use_node_server'] || !$wplc_settings['wplc_enable_initiate_chat']) {
1065
- $initiate_chat_inline_styles = ".init_chat {display:none !important;}";
1066
- wp_add_inline_style('wplc-admin-style', $initiate_chat_inline_styles);
1067
- }
1068
- }
3
  * Node Code
4
  */
5
 
6
+ if (!defined('ABSPATH')) {
7
  exit;
8
  }
9
 
18
  * If not create one for use in the API
19
  *
20
  * @return void
21
+ */
22
+ function wplc_node_server_token_get($reset = false) {
23
+ $tk = '';
24
  if (!$reset) {
25
  $tk = get_option("wplc_node_server_secret_token");
26
  }
27
+ if (empty($tk)) {
28
+ $tk = wplc_node_server_token_create();
29
  update_option("wplc_node_server_secret_token", $tk);
30
  }
31
  return $tk;
35
  function wplc_admin_dashboard() {
36
  $wplc_node_token = wplc_node_server_token_get();
37
  $variables = array("node_token" => $wplc_node_token, "action" => "wordpress");
38
+ $variables = apply_filters("wplc_admin_dashboard_layout_node_request_variable_filter", $variables);
39
  $wplc_settings = wplc_get_options();
40
+ ?>
41
+ <div class='nifty_top_wrapper'>
42
+ <div class="wrap">
43
+ <div class='floating-right-toolbar'>
44
+ <label for="user_list_mobile_control" style="margin-bottom: 0;"><i id="toolbar-item-user_list" class="fa fa-bars fa-fw" title="<?php _e('Toggle user list', 'wp-live-chat-support'); ?>"></i></label>
45
+ <i id="toolbar-item-fullscreen-wp" class="fa fa-clone fa-fw" title="<?php _e('Toggle WordPress Menu for a full screen experience', 'wp-live-chat-support'); ?>."></i>
 
 
 
 
 
 
46
  </div>
47
+ <div id="page-wrapper" style='position:relative;'>
48
+ <div class='nifty_bg_holder'>
49
+ <div class='nifty_bg_holder_text'><img src='<?php echo WPLC_PLUGIN_URL; ?>images/wplc_loading.png' width='50' /><br /><br />
50
+ <div id='nifty_bg_holder_text_inner'>Connecting...</div>
51
+ </div>
52
+ <div class='tcx_tips_hints'></div>
53
+ </div>
54
+
55
  <div class="nifty_admin_overlay" style="display:none">
56
 
57
  </div>
58
+
59
+ <div class="nifty_admin_chat_prompt" style="display:none">
60
+ <div class="nifty_admin_chat_prompt_title" id='nifty_admin_chat_prompt_title'><?php _e('Please Confirm', 'wp-live-chat-support'); ?></div>
61
+ <div class="nifty_admin_chat_prompt_message"></div>
62
+ <div class="nifty_admin_chat_prompt_actions">
63
+ <button class="btn btn-info" id="nifty_admin_chat_prompt_confirm"><?php _e('Confirm', 'wp-live-chat-support'); ?></button>
64
+ <button class="btn btn-secondary" id="nifty_admin_chat_prompt_cancel"><?php _e('Cancel', 'wp-live-chat-support'); ?></button>
65
+ </div>
66
  </div>
67
 
68
  <div id='nifty_wrapper'>
69
  <input type="checkbox" id="user_list_mobile_control" name="user_list_mobile_control" checked="checked">
70
  <div id='user_list' class='col-md-3'>
71
+ <?php if ($wplc_settings['wplc_allow_agents_set_status'] && !empty($variables['aid'])) { ?>
72
  <div id='choose_online'>
73
+ <div id="wplc_agent_status_text" style="display: inline-block; padding-left: 10px;"></div>
74
+ <input type="checkbox" class="wplc_switchery" name="wplc_agent_status" id="wplc_agent_status" <?php echo (wplc_get_agent_accepting(get_current_user_id()) ? ' checked' : ''); ?> />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  </div>
76
+ <?php } ?>
77
+ <div id='user_count'>
78
+ <span id='active_count'>... </span>
79
+ <span id='active_count_string'><?php _e('Active visitors', 'wp-live-chat-support'); ?></span>
80
+ </div>
81
+ <div class='exp_cols'>
82
+ <div class='col1'><?php _e('Name', 'wp-live-chat-support'); ?></div>
83
+ <div class='col3'><?php _e('Agent', 'wp-live-chat-support'); ?></div>
84
+ </div>
85
+ <div class='userListBox_Wrapper'>
86
+ <div class='userListBox'></div>
87
+ </div>
88
+ <div id='agent_list'>
89
+ <h4 id='nifty_agent_heading'><?php _e('Agents', 'wp-live-chat-support'); ?></h4>
90
+ <ul class='online_agent_list'>
91
+ </ul>
92
+ </div>
93
  </div>
94
 
95
  <div id='chat_area' class='col-md-9'>
96
+ <?php if ($variables['include_media_sharing']) { ?>
97
+ <div id="chat_drag_zone" style="display:none;">
98
+ <div id="chat_drag_zone_inner"><span id='drag_zone_inner_text'><?php _e('Drag Files Here', 'wp-live-chat-support'); ?></span></div>
99
+ </div>
100
  <?php } ?>
101
  <div class="chatArea" style='display:none;'>
102
  <div class="chatInfoArea">
103
+ <span class="minChat btn" id="tcx_min_chat" title="<?php _e('Minimize Chat', 'wp-live-chat-support'); ?>"><i class="fas fa-window-close"></i></span>
104
  <div class="dropdown pull-right"></div>
105
 
106
  <div class="btn-group inchat-menu pull-right">
110
  </button>
111
  <div class="dropdown-menu" aria-labelledby='inchat_drop_down'>
112
  <?php if ($variables['include_transfers']) { ?>
113
+ <a href="javascript:void(0);" class='dropdown-item chatTransfer' id='chatTransferLink'><?php _e('Invite Agent', 'wp-live-chat-support'); ?></a>
114
+ <a href="javascript:void(0);" class='dropdown-item chatTransferDepartment' id='chatTransferDepLink'><?php _e('Invite Department', 'wp-live-chat-support'); ?></a>
115
+ <a href="javascript:void(0);" class='dropdown-item chatDirectUserToPagePrompt' id='chatDirectUserToPageLink'><?php _e('Direct User To Page', 'wp-live-chat-support'); ?></a>
116
  <?php } ?>
117
+ <a href="javascript:void(0);" class='dropdown-item chatTranscript' id='chatTranscriptTitle' style='display:none;'><?php _e('Transcript', 'wp-live-chat-support'); ?></a>
118
+ <a href="javascript:void(0);" class='dropdown-item chatClose' id='chatCloseTitle' style="display:none;"><?php _e('Leave chat', 'wp-live-chat-support'); ?></a>
119
+ <a href="javascript:void(0);" class='dropdown-item endChat' id='chatEndTitle'><?php _e('End chat', 'wp-live-chat-support'); ?></a>
120
  </div>
121
  </div>
122
 
125
  <div class='user_gravatar'></div>
126
  </div>
127
  <div class='user_header_wrapper_info'>
128
+ <h3><span class='chatInfoArea-Name'><?php _e('Name', 'wp-live-chat-support'); ?></span></h3>
129
+ <h4><span class='chatInfoArea-Email'><?php _e('Email', 'wp-live-chat-support'); ?></span></h4>
130
+ <p><span class='chatInfoArea-Info1'><?php _e('Something', 'wp-live-chat-support'); ?></span></p>
131
  </div>
132
+
133
  </div>
134
 
135
  <ul class="messages" id="messages"></ul>
136
+
137
+ <?php if ($variables['include_quick_responses']) { ?>
138
+ <div id="quick_response_drawer_handle"><i class="fa fa-bolt" title="<?php _e('Quick Responses', 'wp-live-chat-support'); ?>"></i></div>
139
  <?php } ?>
140
  <div class='typing_preview_wplc' style='display:none;'></div>
141
+ <div class='tcx_join_chat_div'><button class='tcx_join_chat_btn btn btn-success' id='nifty_join_chat_button'><?php _e('Join chat', 'wp-live-chat-support'); ?></button></div>
142
+ <input class="inputMessage wdt-emoji-bundle-enabled" id="inputMessage" placeholder="<?php _e('Type here...', 'wp-live-chat-support'); ?>" />
143
+ <span class="editing_hints"><strong>*<?php _e('bold', 'wp-live-chat-support'); ?>*</strong> <em>_<?php _e('italics', 'wp-live-chat-support'); ?>_</em> <code>`<?php _e('code', 'wp-live-chat-support'); ?>`</code> <code>```<?php _e('preformatted', 'wp-live-chat-support'); ?>```</code></span>
144
+ <img id="wplc_send_msg" class='nifty_send_arrow' style="display:none;" src='<?php echo WPLC_PLUGIN_URL; ?>images/arrow.png' />
145
+
146
+ <?php if ($variables['include_media_sharing']) { ?>
147
+ <label for="nifty_file_input" class='nifty_add_media_button'>
148
+ <i class="nifty_tedit_icon fa fa-paperclip" id="nifty_attach"></i>
149
+ <i class="nifty_attach_icon far fa-circle-notch fa-spin" id="nifty_attach_uploading_icon" style="display:none;"></i>
150
+ <i class="nifty_attach_icon fa fa-check-circle" id="nifty_attach_success_icon" style="display:none;"></i>
151
+ <i class="nifty_attach_icon fa fa-minus-circle" id="nifty_attach_fail_icon" style="display:none;"></i>
152
+ </label>
153
+
154
+ <input type="file" id="nifty_file_input" name="nifty_file_input" style="display:none">
155
+ <?php } else { ?>
156
+ <label for='nifty_add_media' class="nifty_add_media_button"><i class="fa fa-plus"></i></label>
157
+ <input type="checkbox" id="nifty_add_media" />
158
+ <?php } ?>
159
 
160
  </div>
161
  <div class="infoArea">
162
  <div class="dropdown filter-menu pull-right">
163
+ <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" style='margin-right:25px;' title="<?php _e('Filter the user list based on activity.', 'wp-live-chat-support'); ?>" id='nifty_filter_button'>
164
+ Filters
165
+ <span class="caret"></span>
166
+ </button>
167
+ <div class="dropdown-menu">
168
+ <a href="javascript:void(0);" class='dropdown-item filter-new-visitors' id='nifty_new_visitor_item'><?php _e('New Visitors (3 Min)', 'wp-live-chat-support'); ?></a>
169
+ <a href="javascript:void(0);" class='dropdown-item filter-active-chats' id='nifty_active_chats_item'><?php _e('Active Chats', 'wp-live-chat-support'); ?></a>
170
+ <a href="javascript:void(0);" class="dropdown-item filter-referer" id="nifty_referer_item"><?php _e('Page URL', 'wp-live-chat-support'); ?></a>
171
+ <a href="javascript:void(0);" class='dropdown-item filter-clear' id='nifty_clear_filters_item'><?php _e('Clear Filters', 'wp-live-chat-support'); ?></a>
172
+ </div>
173
+ <div class='filter-active-tag-container' style='display:none;'>
174
+ <i class='fa fa-times-circle filter-clear' style="cursor:pointer;"></i>
175
+ <span class='filter-active-tag-inner'></span>
176
+ </div>
177
  </div>
178
 
179
+ <div id="nifty_referer_options" style="display:none;float:right;margin-right:10px;">
180
+ <input placeholder="Page URL" type="text" id="nifty_referer_url" style="width:100%;float:right;">
181
+ <label style="font-weight:normal;">
182
+ <input type="checkbox" id="nifty_referer_contains" style="margin:0;"> <?php _e('Contains', 'wp-live-chat-support'); ?>
183
+ </label>
184
+ </div>
185
+
186
+ <h2 id='nifty_active_chats_heading'><?php _e('Active visitors', 'wp-live-chat-support'); ?></h2>
187
 
 
 
188
  <div class='visitorListBoxHeader'>
189
+ <div class='vcol visCol' id='nifty_vis_col_heading'><?php _e('Visitor', 'wp-live-chat-support'); ?></div>
190
+ <div class='vcol visStatusCol' id='nifty_vis_info_heading'><?php _e('Info', 'wp-live-chat-support'); ?></div>
191
+ <div class='vcol visPageCol' id='nifty_vis_page_heading'><?php _e('Page', 'wp-live-chat-support'); ?></div>
192
+ <div class='vcol visChatStatusCol' id='nifty_vis_status_heading'><?php _e('Chat Status', 'wp-live-chat-support'); ?></div>
193
+ <?php if ($variables['include_departments']) { ?>
194
+ <div class='vcol visChatDepCol' id='nifty_vis_dep_heading'><?php _e('Department', 'wp-live-chat-support'); ?></div>
195
  <?php } ?>
196
  <div class='vcol visActionCol'></div>
197
  </div>
198
+ <?php if ($wplc_settings["wplc_settings_enabled"] == 1) { ?>
199
+ <div class='visitorListBox'>
200
+
201
+ </div>
202
+ <?php } ?>
203
+
204
  </div>
205
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  </div>
207
+ <div class="wdt-emoji-popup">
208
+ <a href="#" class="wdt-emoji-popup-mobile-closer"> &times; </a>
209
+ <div class="wdt-emoji-menu-content">
210
+ <div id="wdt-emoji-menu-header">
211
+ <a class="wdt-emoji-tab" data-group-name="People"></a>
212
+ <a class="wdt-emoji-tab" data-group-name="Nature"></a>
213
+ <a class="wdt-emoji-tab" data-group-name="Foods"></a>
214
+ <a class="wdt-emoji-tab" data-group-name="Activity"></a>
215
+ <a class="wdt-emoji-tab" data-group-name="Places"></a>
216
+ <a class="wdt-emoji-tab" data-group-name="Objects"></a>
217
+ <a class="wdt-emoji-tab" data-group-name="Symbols"></a>
218
+ <a class="wdt-emoji-tab" data-group-name="Flags"></a>
219
+ </div>
220
+ <div class="wdt-emoji-scroll-wrapper">
221
+ <div id="wdt-emoji-menu-items">
222
+ <input id="wdt-emoji-search" type="text" placeholder="<?php _e('Search', 'wp-live-chat-support'); ?>">
223
+ <h3 id="wdt-emoji-search-result-title"><?php _e('Search Results', 'wp-live-chat-support'); ?></h3>
224
+ <div class="wdt-emoji-sections"></div>
225
+ <div id="wdt-emoji-no-result"><?php _e('No emoji found', 'wp-live-chat-support'); ?></div>
226
+ </div>
227
+ </div>
228
+ <div id="wdt-emoji-footer">
229
+ <div id="wdt-emoji-preview">
230
+ <span id="wdt-emoji-preview-img"></span>
231
+ <div id="wdt-emoji-preview-text">
232
+ <span id="wdt-emoji-preview-name"></span><br>
233
+ <span id="wdt-emoji-preview-aliases"></span>
234
+ </div>
235
+ </div>
236
+ <div id="wdt-emoji-preview-bundle">
237
+ <span></span>
238
+ </div>
239
+ <span class="wdt-credit">WDT Emoji Bundle</span>
240
  </div>
241
  </div>
 
 
 
 
242
  </div>
243
+
244
+ <script>
245
+ jQuery(document).ready(function() {
246
+ jQuery("#wplc_footer_loading_icon").hide();
247
+ jQuery("#wplc_footer_message").fadeIn();
248
+ });
249
+ </script>
250
  </div>
251
  </div>
252
+ <?php
253
+ }
254
 
255
+ /**
256
+ * Generates a new Secret Token
257
+ *
258
+ * @return string
259
+ */
260
+ function wplc_node_server_token_create() {
261
+ $the_code = rand(0, 1000) . rand(0, 1000) . rand(0, 1000) . rand(0, 1000) . rand(0, 1000);
262
+ $the_time = time();
263
+ $token = md5($the_code . $the_time);
264
+ return $token;
265
+ }
266
 
267
+ /**
268
+ * Post to the NODE server -
269
+ *
270
+ * @param string $route Route you would like to use for the node server
271
+ * @param string $form_data data to send
272
+ * @return string (or false on fail)
273
+ */
274
+ function wplc_node_server_post($route, $form_data) {
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
  $url = trailingslashit(WPLC_CHAT_SERVER) . trailingslashit(tcx_NODE_END_POINTS_ROUTE) . $route;
277
 
278
+ if (!isset($form_data['token'])) {
279
+ $form_data['token'] = tcx_NODE_END_POINT_TOKEN; //Add the security token
280
  }
281
 
282
+ if (!isset($form_data['api_key'])) {
283
+ $form_data['api_key'] = wplc_node_server_token_get(); //Add the security token
284
  }
285
 
286
+ if (!isset($form_data['origin_url'])) {
287
+ $ajax_url = admin_url('admin-ajax.php');
288
+ $origin_url = str_replace("/wp-admin/admin-ajax.php", "", $ajax_url);
289
+ $form_data['origin_url'] = $origin_url; //Add the security token
290
  }
291
 
292
  // $options = array();
294
  // $result = @file_get_contents($url . "?" . http_build_query($form_data), false, $context);
295
 
296
  $result = wp_remote_get($url . "?" . http_build_query($form_data));
297
+ if (is_array($result)) {
298
  $result = $result['body']; // use the content
299
  }
300
 
301
  if ($result === FALSE) {
302
+ return false;
303
  } else {
304
+ return $result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  }
306
  }
307
+
308
+ /**
309
+ * Loads remote dashboard
310
+ *
311
+ * @return void
312
+ */
313
+ function wplc_admin_dashboard_layout_node($location = 'dashboard') {
314
+ if ($location == 'dashboard') {
315
+ if (!wplc_user_is_agent()) {
316
+ echo "<div class='error below-h1'><h2>" . __("Error", 'wp-live-chat-support') . "</h2><p>" . __("Only chat agents can access this page.", 'wp-live-chat-support') . "</p></div>";
317
+ return;
318
+ }
319
  }
320
+ do_action("wplc_admin_remote_dashboard_above");
321
+ echo "<div id='tcx_content_wrapper'></div>";
322
+ if ($location == 'dashboard') {
323
+ if (!isset($_GET['action']) || 'history' !== $_GET['action']) {
324
+ echo "<div class='wplc_remote_dash_below_contianer'>";
325
+ do_action("wplc_admin_dashboard_render");
326
+ do_action("wplc_admin_remote_dashboard_below");
327
+ echo "</div>";
328
+ }
329
  } else {
330
+ if (!empty($_GET['page']) && 'wplivechat-menu' === $_GET['page']) { // This div is also hidden by js under the same conditions
331
+ echo "<div class='wplc_remote_dash_below_contianer'>";
332
+ do_action("wplc_admin_remote_dashboard_below");
333
+ do_action("wplc_admin_dashboard_render");
334
+ echo "</div>";
335
+ } else {
336
+ $wplc_settings = wplc_get_options();
337
+ if ($wplc_settings['wplc_use_node_server']) {
338
+ if (isset($_GET['page']) && $_GET['page'] === 'wplivechat-menu') { } else {
339
+ if ($wplc_settings['wplc_enable_all_admin_pages']) {
340
+ echo "<div class='wplc_remote_dash_below_contianer'>";
341
+ do_action("wplc_admin_dashboard_render");
342
+ echo "</div>";
343
+ }
344
  }
345
  }
346
  }
347
  }
348
  }
 
349
 
350
+ add_action('admin_enqueue_scripts', 'wplc_enqueue_dashboard_popup_scripts');
351
+ /**
352
+ * Enqueues the scripts for the admin dashboard popup icon and chat box
353
+ * @return void
354
+ */
355
+ function wplc_enqueue_dashboard_popup_scripts() {
356
+ wp_enqueue_script('jquery-ui-draggable');
357
+ wp_enqueue_script('wplc-admin-popup', WPLC_PLUGIN_URL . 'js/wplc_admin_popup.js', array('jquery-ui-draggable'), WPLC_PLUGIN_VERSION);
 
 
 
358
 
359
+ wp_button_pointers_load_scripts('toplevel_page_wplivechat-menu');
360
+ }
361
+
362
+ add_action("admin_footer", "wplc_dashboard_display_decide");
363
+ /**
364
+ * Decide whether or not to display the dashboard layout on an admin page
365
+ * @return void
366
+ */
367
+ function wplc_dashboard_display_decide() {
368
+ $wplc_settings = wplc_get_options();
369
+ if ($wplc_settings['wplc_use_node_server']) {
370
+ //Node in use, load remote dashboard
371
+ if (isset($_GET['page']) && $_GET['page'] === 'wplivechat-menu') { } else {
372
+ /**
373
+ * Check to see if we have enabled "Enable chat dashboard and notifications on all admin pages"
374
+ */
375
+
376
+ if ($wplc_settings['wplc_enable_all_admin_pages']) {
377
+ wplc_admin_dashboard_layout_node('other');
378
+ echo '<div class="floating-right-toolbar">';
379
+ echo '<label for="user_list_tcx_control" style="margin-bottom: 0; display:none;"></label>';
380
+ echo '<i id="toolbar-item-open-tcx" class="fa fa-fw" style="background:url(\'' . plugins_url('../images/tcx48px.png', __FILE__) . '\') no-repeat; background-size: cover;"></i>';
381
+ echo '</div>';
382
+ }
383
  }
384
  }
385
  }
 
386
 
387
+ /**
388
+ * Loads remote dashboard scripts and styles
389
+ *
390
+ * @return void
391
+ */
392
+ function wplc_admin_remote_dashboard_scripts($wplc_settings) {
393
+ $wplc_current_user = get_current_user_id();
394
+ if (wplc_user_is_agent($wplc_current_user)) {
395
+ $user_info = get_userdata($wplc_current_user);
396
+ $user_array = wplc_get_agent_users();
397
+ $a_array = array();
398
+ if ($user_array) {
399
+ foreach ($user_array as $user) {
400
+ $a_array[$user->ID] = array();
401
+ $a_array[$user->ID]['name'] = $user->display_name;
402
+ $a_array[$user->ID]['display_name'] = $user->display_name;
403
+ $a_array[$user->ID]['md5'] = md5($user->user_email);
404
+ $a_array[$user->ID]['email'] = md5($user->user_email);
405
+ }
 
 
 
 
406
  }
 
407
 
408
+ wp_register_script('wplc-admin-js-sockets', WPLC_PLUGIN_URL . "js/vendor/sockets.io/socket.io.slim.js", false, WPLC_PLUGIN_VERSION, false);
409
+ wp_enqueue_script('wplc-admin-js-sockets');
410
+
411
+ wp_register_script('wplc-admin-js-bootstrap', WPLC_PLUGIN_URL . "js/vendor/bootstrap/dist/js/bootstrap.js", array("wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false);
412
+ wp_enqueue_script('wplc-admin-js-bootstrap');
413
+
414
+ wplc_register_common_node();
415
+
416
+ // NB: This causes Failed to initVars ReferenceError: wplc_show_date is not defined when uncommented and enabled
417
+ if (!$wplc_settings['wplc_disable_emojis']) {
418
+ wp_register_script('wplc-admin-js-emoji', WPLC_PLUGIN_URL . "js/vendor/wdt-emoji/emoji.min.js", array("wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false);
419
+ wp_enqueue_script('wplc-admin-js-emoji');
420
+ wp_register_script('wplc-admin-js-emoji-bundle', WPLC_PLUGIN_URL . "js/vendor/wdt-emoji/wdt-emoji-bundle.min.js", array("wplc-admin-js-emoji"), WPLC_PLUGIN_VERSION, false);
421
+ wp_enqueue_script('wplc-admin-js-emoji-bundle');
422
+ }
423
+
424
+ wp_register_script('md5', WPLC_PLUGIN_URL . 'js/md5.js', array("wplc-admin-js-sockets"), false, false);
425
+ wp_enqueue_script('md5');
426
+
427
+ $dependencies = array();
428
+ if (!$wplc_settings['wplc_disable_emojis']) {
429
+ $dependencies[] = "wplc-admin-js-emoji-bundle";
430
+ }
431
+ wp_register_script('wplc-admin-js-agent', WPLC_PLUGIN_URL . 'js/wplc_agent_node.js', $dependencies, WPLC_PLUGIN_VERSION, false);
432
+ wp_localize_script('wplc-admin-js-agent', "tcx_ping_sound_notification_enabled", array('value' => boolval($wplc_settings['wplc_enable_msg_sound'])));
433
+
434
+ wp_register_script('my-wplc-admin-chatbox-ui-events', WPLC_PLUGIN_URL . 'js/wplc_u_admin_chatbox_ui_events.js', array('jquery'), WPLC_PLUGIN_VERSION, true);
435
+ wp_enqueue_script('my-wplc-admin-chatbox-ui-events');
436
+
437
+
438
+
439
+ $wplc_et_ajax_nonce = wp_create_nonce("wplc_et_nonce");
440
+ wp_register_script('wplc_transcript_admin', WPLC_PLUGIN_URL . 'js/wplc_transcript.js', null, '', true);
441
+ $wplc_transcript_localizations = array(
442
+ 'ajax_nonce' => $wplc_et_ajax_nonce,
443
+ 'string_loading' => __("Sending transcript...", 'wp-live-chat-support'),
444
+ 'string_title' => __("Chat Transcript", 'wp-live-chat-support'),
445
+ 'string_close' => __("Close", 'wp-live-chat-support'),
446
+ 'string_chat_emailed' => __("The chat transcript has been emailed.", 'wp-live-chat-support'),
447
+ 'string_error1' => __("There was a problem emailing the chat.", 'wp-live-chat-support')
448
+ );
449
+ wp_localize_script('wplc_transcript_admin', 'wplc_transcript_nonce', $wplc_transcript_localizations);
450
+ wp_enqueue_script('wplc_transcript_admin');
451
+
452
+ $wplc_node_token = wplc_node_server_token_get();
453
+
454
+ if (isset($_GET['page']) && $_GET['page'] === 'wplivechat-menu') {
455
+ wp_localize_script('wplc-admin-js-agent', 'tcx_in_dashboard', array('value' => true));
456
+ } else {
457
+ wp_localize_script('wplc-admin-js-agent', 'tcx_in_dashboard', array('value' => false));
458
+ }
459
+
460
+ $inline_error_message = "<div class='error below-h1' style='display:none;' id='tcx_inline_connection_error'>
461
  <p>" . __("Connection Error", 'wp-live-chat-support') . "<br /></p>
462
  <p>" . __("We are having some trouble contacting the server. Please try again later.", 'wp-live-chat-support') . "</p>
463
  </div>";
464
+ wp_localize_script('wplc-admin-js-agent', 'tcx_remote_form_error', $inline_error_message);
465
 
466
 
467
+ wp_localize_script('wplc-admin-js-agent', 'tcx_enable_visitor_sound', array('value' => $wplc_settings['wplc_enable_visitor_sound']));
468
 
469
+ $agent_display_name = $user_info->display_name;
470
 
471
+ wp_localize_script('wplc-admin-js-agent', 'agent_id', "" . $wplc_current_user);
472
+ wp_localize_script('wplc-admin-js-agent', 'tcx_agent_name', apply_filters("wplc_agent_display_name_filter", $agent_display_name));
473
+ wp_localize_script('wplc-admin-js-agent', 'nifty_api_key', wplc_node_server_token_get());
474
 
475
+ //For node verification
476
+ wplc_check_guid();
477
 
478
+ wp_localize_script('wplc-admin-js-agent', 'wplc_guid', get_option('WPLC_GUID', ''));
479
+ wp_localize_script('wplc-admin-js-agent', 'tcx_agent_verification_end_point', rest_url('wp_live_chat_support/v1/validate_agent'));
480
+ wp_localize_script('wplc-admin-js-agent', 'tcx_disable_add_message', array('value' => true));
481
+ wp_localize_script('wplc-admin-js-agent', 'wplc_nonce', wp_create_nonce("wplc"));
482
+ wp_localize_script('wplc-admin-js-agent', 'wplc_cid', null);
483
+ wp_localize_script('wplc-admin-js-agent', 'wplc_chat_name', null);
 
 
 
 
 
 
 
 
 
484
 
485
+ $wplc_chat_detail = array(
486
+ 'name' => $wplc_settings['wplc_show_name'],
487
+ 'avatar' => $wplc_settings['wplc_show_avatar'],
488
+ 'date' => $wplc_settings['wplc_show_date'],
489
+ 'time' => $wplc_settings['wplc_show_time'],
490
+ );
491
+ wp_localize_script('wplc-admin-js-agent', 'wplc_show_chat_detail', $wplc_chat_detail);
492
+ wp_localize_script('wplc-admin-chat-server', 'wplc_show_chat_detail', $wplc_chat_detail);
493
 
494
+ wp_localize_script('wplc-admin-js-agent', 'wplc_agent_data', $a_array);
495
+ wp_localize_script('wplc-admin-js-agent', 'all_agents', $a_array);
496
 
497
+ wp_localize_script('wplc-admin-js-agent', 'wplc_url', plugins_url('', dirname(__FILE__)));
498
+
499
+ if (isset($wplc_settings['wplc_settings_enabled']) && intval($wplc_settings["wplc_settings_enabled"]) == 2) {
500
+ $wplc_disabled_html = __("Chat is disabled in settings area, re-enable", 'wp-live-chat-support');
501
+ $wplc_disabled_html .= " <a href='?page=wplivechat-menu-settings'>" . __("here", 'wp-live-chat-support') . "</a>";
502
+ wp_localize_script('wplc-admin-js-agent', 'wplc_disabled', array('value' => true));
503
+ wp_localize_script('wplc-admin-js-agent', 'wplc_disabled_html', $wplc_disabled_html);
504
+ } else {
505
+ wp_localize_script('wplc-admin-js-agent', 'wplc_disabled', array('value' => false));
506
+ }
507
 
508
+ //Added rest nonces
509
+ if (class_exists("WP_REST_Request")) {
510
+ wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_enabled', array('value' => true));
511
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_token', get_option('wplc_api_secret_token'));
512
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_endpoint', rest_url('wp_live_chat_support/v1'));
513
  wp_localize_script('wplc-admin-js-agent', 'tcx_override_upload_url', rest_url('wp_live_chat_support/v1/remote_upload'));
514
+ wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_nonce', wp_create_nonce('wp_rest'));
515
+ } else {
516
+ wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_enabled', array('value' => false));
 
517
  wp_localize_script('wplc-admin-js-agent', 'wplc_restapi_nonce', '');
518
+ }
519
 
520
+ // $agent_tagline = apply_filters( "wplc_filter_simple_agent_data_agent_tagline", '', get_current_user_id() );
521
+ $agent_tagline = get_user_meta(intval(get_current_user_id()), 'wplc_user_tagline', true);
522
+ $head_data = array(
523
+ 'tagline' => $agent_tagline
524
+ );
525
+ wp_localize_script('wplc-admin-js-agent', 'wplc_head_data', $head_data);
526
+ wp_localize_script('wplc-admin-js-agent', 'wplc_user_chat_notification_prefix', __("User received notification:", 'wp-live-chat-support'));
527
 
528
+ wp_localize_script('wplc-admin-js-agent', 'tcx_valid_direct_to_page_array', wplc_node_pages_posts_array());
529
 
530
+ wp_localize_script('wplc-admin-js-agent', 'tcx_ringer_count', array('value' => intval($wplc_settings['wplc_new_chat_ringer_count'])));
531
 
532
+ wp_localize_script('wplc-admin-js-agent', 'tcx_new_chat_notification_title', __('New chat received', 'wp-live-chat-support'));
533
+ wp_localize_script('wplc-admin-js-agent', 'tcx_new_chat_notification_text', __("A new chat has been received. Please go the 'Live Chat' page to accept the chat", 'wp-live-chat-support'));
534
 
535
+ $wplc_notification_icon = plugin_dir_url(dirname(__FILE__)) . 'images/wplc_notification_icon.png';
536
+ wp_localize_script('wplc-admin-js-agent', 'tcx_new_chat_notification_icon', $wplc_notification_icon);
537
 
538
+ do_action("wplc_admin_remoter_dashboard_scripts_localizer"); //For pro localization of agents list, and departments
539
 
540
+ wp_enqueue_script('wplc-admin-js-agent');
541
 
542
+ wp_register_script('wplc-admin-chat-server', WPLC_PLUGIN_URL . 'js/wplc_server.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
543
+ wp_enqueue_script('wplc-admin-chat-server');
544
 
545
+ wp_localize_script('wplc-admin-chat-server', 'wplc_datetime_format', array(
546
+ 'date_format' => get_option('date_format'),
547
+ 'time_format' => get_option('time_format'),
548
+ ));
 
 
 
549
 
550
+ wp_register_script('wplc-admin-chat-events', WPLC_PLUGIN_URL . 'js/wplc_u_admin_events.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
551
+ wp_enqueue_script('wplc-admin-chat-events');
552
+ }
553
+ }
554
 
555
 
556
+ /**
557
+ * Loads remote dashboard styles
558
+ *
559
+ * @return void
560
+ */
561
+ function wplc_admin_remote_dashboard_styles() {
562
  $wplc_settings = wplc_get_options();
563
 
564
+ wp_register_style('wplc-admin-style', WPLC_PLUGIN_URL . "css/chat_dashboard/admin_style.css", false, WPLC_PLUGIN_VERSION);
565
+ wp_enqueue_style('wplc-admin-style');
566
 
567
+ if (!isset($wplc_settings['wplc_show_avatar']) || (isset($wplc_settings['wplc_show_avatar']) && intval($wplc_settings['wplc_show_avatar']) == 0)) {
568
+ wp_add_inline_style('wplc-admin-style', ".wplc-user-message, .wplc-admin-message { padding-left: 0 !important; }");
569
+ } else if (!isset($wplc_settings['wplc_show_name']) || (isset($wplc_settings['wplc_show_name']) && intval($wplc_settings['wplc_show_name']) == 0)) {
570
+ //User has enabled the gravatar, but has chosen to hide the user name.
571
+ //This causes some issues with admin display so let's just add some different styling to get around this
572
+ $inline_identity_css =
573
+ "
 
574
  .wplc-admin-message-avatar, .wplc-user-message-avatar {
575
  max-width:28px !important;
576
  max-height:28px !important;
596
  }
597
  ";
598
 
599
+ wp_add_inline_style('wplc-admin-style', $inline_identity_css);
600
  }
601
 
602
+ wp_register_style('wplc-admin-style-bootstrap', WPLC_PLUGIN_URL . "css/bootstrap.css", false, WPLC_PLUGIN_VERSION);
603
+ wp_enqueue_style('wplc-admin-style-bootstrap');
604
 
605
+ if (!$wplc_settings['wplc_disable_emojis']) {
606
+ wp_register_style('wplc-admin-style-emoji', WPLC_PLUGIN_URL . "js/vendor/wdt-emoji/wdt-emoji-bundle.css", false, WPLC_PLUGIN_VERSION);
607
+ wp_enqueue_style('wplc-admin-style-emoji');
608
+ }
 
 
 
609
 
610
+ do_action("wplc_admin_remote_dashboard_styles_hook");
611
+ }
612
+
613
+ /*
614
  * Add action for notice checks
615
  */
616
+ if (!function_exists("wplc_active_chat_box_notices")) {
617
+ if (isset($_GET['page']) && $_GET['page'] === "wplivechat-menu") {
618
+ add_action("wplc_admin_remote_dashboard_above", "wplc_active_chat_box_notices");
619
+ }
620
+ }
621
 
622
+ add_action("admin_notices", "wplc_node_v8_plus_notice_dismissable");
623
+ /*
624
  * Displays an admin notice (which can be dismissed), to notify any V8+ users of the node option (if not already checked)
625
  */
626
+ function wplc_node_v8_plus_notice_dismissable() {
627
+ $page = '';
628
+ if (isset($_GET['page'])) {
629
+ $page = preg_replace('/[^a-z0-9-]/', '', sanitize_text_field($_GET['page']));
 
 
 
 
630
  }
631
+ if (!empty($page) && strpos($page, 'wplivechat') === 0) { // only if it begins with wplivechat
632
+ if (isset($_GET['wplc_dismiss_notice_v8']) && $_GET['wplc_dismiss_notice_v8'] === "true") {
633
+ update_option("wplc_node_v8_plus_notice_dismissed", 'true');
634
+ }
635
+
636
+ $wplc_settings = wplc_get_options();
637
+ if (!$wplc_settings['wplc_use_node_server']) {
638
+ //User is not on node, let's check if they have seen this notice before, if not, let's show a notice
639
+ $wplc_has_notice_been_dismissed = get_option("wplc_node_v8_plus_notice_dismissed", false);
640
+ if ($wplc_has_notice_been_dismissed === false) {
641
+ //Has not been dismissed
642
+ $output = "<div class='notice notice-warning' style='border-color: #0180bc;'>";
643
+ $output .= "<p><strong>" . __('Welcome to V8 of WP Live Chat by 3CX', 'wp-live-chat-support') . "</strong></p>";
644
+ $output .= "<p>" . __('Did you know, this version features high speed message delivery, agent to agent chat, and a single window layout?', 'wp-live-chat-support') . "</p>";
645
+ $output .= "<p>" . __('To activate this functionality please navigate to Live Chat -> Settings -> Advanced Features -> And enable 3CX High Performance Chat Cloud Servers.', 'wp-live-chat-support') . "</p>";
646
+
647
+ $output .= "<p>";
648
+ $output .= "<a href='?page=wplivechat-menu-settings#tabs-beta' class='button button-primary'>" . __("Show me!", 'wp-live-chat-support') . "</a> ";
649
+ $output .= "<a href='?page=" . $page . "&wplc_dismiss_notice_v8=true' id='wplc_v8_dismiss_node_notice' class='button'>" . __("Don't Show This Again", 'wp-live-chat-support') . "</a>";
650
+ $output .= "</p>";
651
+ $output .= "</div>";
652
+ echo $output;
653
+ }
654
  }
655
  }
656
  }
 
657
 
658
+ add_filter('rest_url', 'wplc_node_rest_url_ssl_fix');
659
+ /**
660
+ * Changes the REST URL to include the SSL version if we are using SSL
661
+ * See https://core.trac.wordpress.org/ticket/36451
662
+ */
663
+ function wplc_node_rest_url_ssl_fix($url) {
664
+ if (is_ssl()) {
665
+ $url = set_url_scheme($url, 'https');
666
+ return $url;
667
+ }
668
+ return $url;
669
+ }
670
 
671
+ /**
672
+ * Returns an array of pages/posts available on the site
673
+ */
674
+ function wplc_node_pages_posts_array() {
675
  $r = array(
676
+ 'depth' => 0,
677
+ 'child_of' => 0,
678
+ 'echo' => false,
679
+ 'id' => '',
680
+ 'class' => '',
681
+ 'show_option_none' => '',
682
+ 'show_option_no_change' => '',
683
+ 'option_none_value' => '',
684
+ 'value_field' => 'ID',
685
  );
686
 
687
+ $pages = get_pages($r);
688
+ $posts = get_posts(array('posts_per_page' => -1));
689
 
690
+ $posts_pages = array_merge($pages, $posts);
691
 
692
+ $return_array = array();
693
 
694
+ foreach ($posts_pages as $key => $value) {
695
+ $post_page_id = $value->ID;
696
+ $post_page_title = $value->post_title;
697
 
698
+ $return_array[get_permalink($post_page_id)] = $post_page_title;
699
+ }
700
 
701
+ return $return_array;
702
+ }
703
 
704
 
705
 
706
+ add_action("wplc_admin_remoter_dashboard_scripts_localizer", "wplc_admin_remote_dashboard_dynamic_translation_handler");
707
+ /*
708
  * Localizes an array of strings and ids in the dashboard which need to be replaced
709
  * Loads the custom JS file responsible for replacing the content dynamically.
710
  */
711
+ function wplc_admin_remote_dashboard_dynamic_translation_handler() {
712
 
713
+ wp_register_script('wplc-admin-dynamic-translation', WPLC_PLUGIN_URL . 'js/wplc_admin_dynamic_translations.js', array("wplc-admin-js-agent", "wplc-admin-js-sockets", "jquery"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
714
 
715
  $wplc_dynamic_translation_array = array(
716
  'nifty_bg_holder_text_inner' => __('Connecting...', 'wp-live-chat-support'),
750
 
751
  wp_localize_script('wplc-admin-dynamic-translation', 'wplc_dynamic_translation_array', $wplc_dynamic_translation_array);
752
  wp_enqueue_script('wplc-admin-dynamic-translation');
753
+ }
 
754
 
755
 
756
 
757
 
758
+ add_action("wplc_admin_remoter_dashboard_scripts_localizer", "wplc_admin_remote_dashboard_localize_variables");
759
+ /*
760
  * Localizes all the admin variables
761
  */
762
+ function wplc_admin_remote_dashboard_localize_variables() {
763
+ $wplc_settings = wplc_get_options();
764
+ $user_id = get_current_user_id();
765
+ $user_department = get_user_meta($user_id, "wplc_user_department", true);
766
+ $department_array = array();
767
+ $departments = wplc_get_all_deparments_mrg();
768
+ if ($departments) {
769
+ foreach ($departments as $dep) {
770
+ $department_array[$dep->id] = $dep->name;
771
+ }
772
  }
773
+ $departments['any'] = __("None", 'wp-live-chat-support');
774
+ $default_department = $wplc_settings['wplc_default_department'];
775
+ wp_localize_script('wplc-admin-js-agent', 'tcx_departments', $department_array);
776
+
777
+ if ($wplc_settings['wplc_allow_department_selection'] && !empty($department_array)) {
778
+ if (intval($default_department) >= 0) {
779
+ wp_localize_script('wplc-admin-js-agent', 'tcx_default_department_tag', $department_array[$default_department]);
780
+ } else {
781
+ wp_localize_script('wplc-admin-js-agent', 'tcx_default_department_tag', $departments['any']);
782
+ }
783
  } else {
784
+ wp_localize_script('wplc-admin-js-agent', 'tcx_default_department_tag', 'any');
785
  }
 
 
 
786
 
787
+ if (!empty($user_department)) {
788
+ wp_localize_script('wplc-admin-js-agent', 'tcx_agent_department', $user_department);
789
+ }
790
+ wp_register_script('wplc-admin-chat-events-pro', WPLC_PLUGIN_URL . 'js/wplc_admin_pro_events.js', array("wplc-admin-js-agent", "wplc-admin-chat-events", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
791
+ wp_enqueue_script('wplc-admin-chat-events-pro');
792
+ wp_register_script('wplc-admin-tcx-event-tracking-pro', WPLC_PLUGIN_URL . 'js/wplc_tcx_admin_events.js', array("wplc-admin-js-agent", "wplc-admin-chat-events", "wplc-admin-chat-server"), WPLC_PLUGIN_VERSION, false); //Added this for async storage calls
793
+ wp_enqueue_script('wplc-admin-tcx-event-tracking-pro');
794
  }
 
 
 
 
 
795
 
796
+ add_filter("wplc_admin_dashboard_layout_node_request_variable_filter", "wplc_admin_dashboard_layout_node_request_add_mrg_variables", 10, 1);
797
+ /*
798
  * Adds the Pro request variables to our node request
799
  */
800
+ function wplc_admin_dashboard_layout_node_request_add_mrg_variables($variables) {
801
+ if (is_array($variables)) {
802
+ $variables['include_filters'] = true;
803
+ $variables['include_transfers'] = true;
804
+ $variables['include_media_sharing'] = true;
805
+ $variables['include_quick_responses'] = true;
806
+ $variables['include_departments'] = true;
807
+ $variables['aid'] = get_current_user_id();
808
+ $variables['agent_count'] = wplc_get_online_agent_users_count();
809
+ }
810
+ return $variables;
811
+ }
812
 
813
+ add_filter("wplc_admin_remote_dashboard_localize_tips_array", "wplc_admin_remote_dashboard_localize_tips_array_mrg_handler", 1, 1);
814
+ /*
815
  * Overrides the tip array in the Pro add-on
816
  */
817
+ function wplc_admin_remote_dashboard_localize_tips_array_mrg_handler($tip_array) {
818
+ $tip_array = array(
819
+ "0" => "<p>" . __("You can transfer chats from within a chat by clicking on the in chat menu, and selecting Transfer Chat or Transfer Department", 'wp-live-chat-support') . "</p>",
820
+ "1" => "<p>" . __("You can share files quickly when in a chat, by simply dragging a file into the chat window!", 'wp-live-chat-support') . "</p>",
821
+ "2" => "<p>" . __("You can now move between chats without ending/closing an open chat", 'wp-live-chat-support') . "</p>"
822
+ );
823
+ return $tip_array;
824
+ }
825
 
826
 
827
+ /**
828
+ * Return a count of unread messages for a specific agent from a specific agent
829
+ *
830
+ * @param [intval] $ato Agent ID
831
+ * @param [intval] $afrom Agent ID
832
+ * @return [intval] Count
833
+ */
834
+ function wplc_return_unread_agent_messages_mrg($ato = 0, $afrom = 0) {
835
  global $wpdb;
836
  global $wplc_tblname_msgs;
837
+ $count = $wpdb->get_var($wpdb->prepare("SELECT count(id) FROM $wplc_tblname_msgs WHERE ato = %d AND afrom = %d AND status = 0", $ato, $afrom));
838
  return $count;
839
+ }
840
 
841
+ add_action("wplc_admin_remote_dashboard_above", "wplc_admin_remote_dashboard_quick_responses_container_mrg");
842
+ /*
843
  * Adds the quick response container
844
  */
845
+ function wplc_admin_remote_dashboard_quick_responses_container_mrg() {
846
 
847
  $wplc_settings = wplc_get_options();
848
+ $wplc_quick_response_order_by = isset($wplc_settings['wplc_quick_response_orderby']) ? sanitize_text_field($wplc_settings['wplc_quick_response_orderby']) : 'title';
849
+ $wplc_quick_response_order = isset($wplc_settings['wplc_quick_response_order']) ? sanitize_text_field($wplc_settings['wplc_quick_response_order']) : 'DESC';
850
  $args = array(
851
+ 'posts_per_page' => -1,
852
+ 'offset' => 0,
853
+ 'category' => '',
854
+ 'order' => $wplc_quick_response_order,
855
+ 'orderby' => $wplc_quick_response_order_by != 'number' ? $wplc_quick_response_order_by : 'meta_value_num',
856
+ 'include' => '',
857
+ 'exclude' => '',
858
+ 'meta_key' => $wplc_quick_response_order_by != 'number' ? '' : 'wplc_quick_response_number',
859
+ 'meta_value' => '',
860
+ 'post_type' => 'wplc_quick_response',
861
+ 'post_mime_type' => '',
862
+ 'post_parent' => '',
863
+ 'post_status' => 'publish',
864
+ 'suppress_filters' => true
865
+ );
866
  $posts_array = get_posts($args);
867
  echo '<div id="quick_response_drawer_container" style="display:none;">';
868
+ echo '<h5>' . __("Quick Responses", 'wp-live-chat-support') . '</h5>';
869
+ echo '<hr>';
870
+ //Add quick responses
871
+ if ($posts_array) {
872
+ foreach ($posts_array as $post) {
873
+ echo '<div class="quick_response_item">' . $post->post_content . '</div>';
874
+ }
875
  } else {
876
+ echo "<div style='position: absolute; top: 23px; bottom: 0; left: 10px; right: 0; margin: auto; height: 20px;'>";
877
+ echo __("No quick responses found", 'wp-live-chat-support') . " - <a target='_blank' href='" . admin_url('post-new.php?post_type=wplc_quick_response') . "'>" . __("Add New Quick Response", 'wp-live-chat-support') . "</a>";
878
+ echo "</div>";
879
  }
880
  echo '</div>';
881
+ }
882
 
883
 
884
+ add_filter("wplc_agent_display_name_filter", "wplc_agent_display_name_filter_control_mrg", 10, 1);
885
+ /*
886
  * Filters the agent display name
887
  */
888
+ function wplc_agent_display_name_filter_control_mrg($wplc_display_name) {
889
+ $wplc_settings = wplc_get_options();
890
+ if (!empty($wplc_settings['wplc_use_wp_name'])) {
891
+ return $wplc_display_name;
892
+ } else {
893
+ if (!empty($wplc_settings['wplc_chat_name'])) {
894
+ $wplc_display_name = $wplc_settings['wplc_chat_name'];
895
+ }
896
  }
897
+ return $wplc_display_name;
898
  }
 
 
899
 
900
+ add_action("wplc_admin_remote_dashboard_styles_hook", "wplc_admin_remote_dashboard_styles_mrg");
901
+ /**
902
+ * Loads remote dashboard styles
903
+ *
904
+ * @return void
905
+ */
906
+ function wplc_admin_remote_dashboard_styles_mrg() {
907
+ $wplc_settings = wplc_get_options();
908
 
909
+ if (!$wplc_settings['wplc_use_node_server'] || !$wplc_settings['wplc_enable_initiate_chat']) {
910
+ $initiate_chat_inline_styles = ".init_chat {display:none !important;}";
911
+ wp_add_inline_style('wplc-admin-style', $initiate_chat_inline_styles);
912
+ }
913
+ }
modules/webhooks_manager.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
 
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
  }
6
 
7
  global $wplc_webhook_table, $wplc_webhook_events;
8
  $wplc_webhook_table = $wpdb->prefix . "wplc_webhooks";
9
 
10
  //Use these when sending a payload
11
- $wplc_webhook_events = array (
12
- 0 => __("Agent Login", 'wp-live-chat-support'),
13
- 3 => __("New Visitor", 'wp-live-chat-support'),
14
- 4 => __("Chat Request", 'wp-live-chat-support'),
15
- 5 => __("Agent Accept", 'wp-live-chat-support'),
16
- 6 => __("Settings Changed", 'wp-live-chat-support')
17
- );
18
 
19
  add_action("wplc_activate_hook", "wplc_webhook_db_setup", 10);
20
  add_action("wplc_update_hook", "wplc_webhook_db_setup", 10);
21
  /*
22
  * Updates/Creates the required tables in order to use devices on node
23
  */
24
- function wplc_webhook_db_setup(){
25
- global $wplc_webhook_table;
26
 
27
- $wplc_webhooks_sql = "
28
  CREATE TABLE " . $wplc_webhook_table . " (
29
  id int(11) NOT NULL AUTO_INCREMENT,
30
  url varchar(700) NULL,
@@ -34,244 +34,244 @@ function wplc_webhook_db_setup(){
34
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
35
  ";
36
 
37
- dbDelta($wplc_webhooks_sql);
38
  }
39
 
40
- add_action("wplc_hook_menu_mid","wplc_webhooks_manager_menu",11,1);
41
  /*
42
  * Adds a Webhooks menu item to admin menu
43
  */
44
  function wplc_webhooks_manager_menu($cap) {
45
- $wplc_settings = wplc_get_options();
46
- if ($wplc_settings['wplc_use_node_server']) {
47
- //Only add this menu item if user is using node.
48
- if (current_user_can("manage_options")) {
49
- add_submenu_page('wplivechat-menu', __('Webhooks', 'wp-live-chat-support'), __('Webhooks', 'edit_posts'), $cap[0], 'wplivechat-menu-webhooks-page', 'wplc_webhooks_page');
50
- }
51
  }
 
52
  }
53
 
54
  /*
55
  * Draws the webhooks page
56
  */
57
- function wplc_webhooks_page(){
58
- wplc_webhook_header_check();
59
 
60
- $add_webhook_btn = isset($_GET["wplc_action"]) && $_GET["wplc_action"] !== "delete_webhook_confirmed" ? "" : "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=add_webhook' class='button button-secondary'>". __("Add New", 'wp-livechat') ."</a>";
61
 
62
- $content = "<div class='wrap wplc_wrap'>";
63
- $content .= "<h2>" . __('Web Hooks', 'wp-live-chat-support') . " " . $add_webhook_btn . "</h2>";
64
 
65
- if(isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'add_webhook'){
66
- $content .= wplc_webhooks_add_form();
67
- } else if(isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'edit_webhook'){
68
- $content .= wplc_webhooks_add_form(true, $_GET['id']);
69
- } else if(isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'delete_webhook'){
70
- $content .= wplc_webhooks_confirm_delete_prompt();
71
- } else {
72
- $content .= wplc_webhooks_table();
73
- }
74
-
75
- $content .= "</div>"; //Close Wrap
76
-
77
 
78
- echo $content;
 
79
  }
80
 
81
- function wplc_webhook_header_check(){
82
- if(isset($_POST['add_webhook'])){
83
- //User is trying to add a webhook
84
- if(wplc_webhook_add_webhook()){
85
- echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook created", 'wp-live-chat-support') . "</p>";
86
- } else {
87
- echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be created", 'wp-live-chat-support') . "</p>";
88
- }
89
  }
 
90
 
91
- if(isset($_POST['edit_webhook'])){
92
- //User is trying to edit a webhook
93
- if(wplc_webhook_edit_webhook()){
94
- echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook edited", 'wp-live-chat-support') . "</p>";
95
- } else {
96
- echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be edited", 'wp-live-chat-support') . "</p>";
97
- }
98
  }
 
99
 
100
- if(isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'delete_webhook_confirmed'){
101
- if (!isset($_GET['wplc_webhook_nonce']) || !wp_verify_nonce($_GET['wplc_webhook_nonce'], 'wplc_webhook_nonce')){
102
- wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
103
- }
104
 
105
- $webhook_id = isset($_GET['id']) ? intval($_GET['id']) : false;
106
- if($webhook_id !== false){
107
- if(wplc_webhook_delete_webhook($webhook_id)){
108
- echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook deleted", 'wp-live-chat-support') . "</p>";
109
- } else {
110
- echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be delete", 'wp-live-chat-support') . "</p>";
111
- }
112
- }
113
  }
 
114
  }
115
 
116
- function wplc_webhook_add_webhook(){
117
- global $wpdb;
118
- global $wplc_webhook_table;
119
 
120
- if(isset($_POST['add_webhook_event'])){
121
- if (!isset($_POST['wplc_webhook_nonce']) || !wp_verify_nonce($_POST['wplc_webhook_nonce'], 'wplc_webhook_nonce')){
122
- wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
123
- }
 
 
 
 
124
 
125
- $event = intval($_POST['add_webhook_event']);
126
- $action_url = sanitize_text_field($_POST['add_webhook_domain']);
127
- $method = isset($_POST['add_webhook_method']) ? sanitize_text_field($_POST['add_webhook_method']) : "GET" ;
128
-
129
- $sql = "INSERT INTO $wplc_webhook_table SET `url` = '%s', `action` = '%s', `method` = '%s' ";
130
- $sql = $wpdb->prepare($sql, $action_url, $event, $method);
131
- $wpdb->query($sql);
132
- if ($wpdb->last_error) {
133
- return false;
134
- } else {
135
- return true;
136
- }
137
  } else {
138
- return false;
139
  }
 
 
 
140
  }
141
 
142
- function wplc_webhook_edit_webhook(){
143
- global $wpdb;
144
- global $wplc_webhook_table;
145
 
146
- $webhook_id = isset($_POST['edit_webhook_id']) ? intval($_POST['edit_webhook_id']) : false;
147
- if(isset($_POST['add_webhook_event']) && $webhook_id !== false){
148
- if (!isset($_POST['wplc_webhook_nonce']) || !wp_verify_nonce($_POST['wplc_webhook_nonce'], 'wplc_webhook_nonce')){
149
- wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
150
- }
151
 
152
- $event = intval($_POST['add_webhook_event']);
153
- $action_url = sanitize_text_field($_POST['add_webhook_domain']);
154
- $method = isset($_POST['add_webhook_method']) ? sanitize_text_field($_POST['add_webhook_method']) : "GET" ;
155
-
156
- $sql = "UPDATE $wplc_webhook_table SET `url` = '%s', `action` = '%s', `method` = '%s' WHERE `id` = '%d' LIMIT 1";
157
- $sql = $wpdb->prepare($sql, $action_url, $event, $method, $webhook_id);
158
- $wpdb->query($sql);
159
- if ($wpdb->last_error) {
160
- return false;
161
- } else {
162
- return true;
163
- }
164
  } else {
165
- return false;
166
  }
 
 
 
167
  }
168
 
169
- function wplc_webhook_delete_webhook($webhook_id = false){
170
- global $wpdb;
171
- global $wplc_webhook_table;
172
-
173
- if($webhook_id !== false){
174
- $sql = "DELETE FROM $wplc_webhook_table WHERE `id` = '%d' LIMIT 1";
175
- $sql = $wpdb->prepare($sql, $webhook_id);
176
- $wpdb->query($sql);
177
- if ($wpdb->last_error) {
178
- return false;
179
- } else {
180
- return true;
181
- }
182
  } else {
183
- return false;
184
  }
 
 
 
185
  }
186
 
187
  /*
188
  * Return all webhooks from database
189
  */
190
- function wplc_webhooks_get_all_db($where = false, $id = false){
191
- global $wpdb;
192
- global $wplc_webhook_table;
193
-
194
- $where = ($where === false) ? "" : $where;
195
-
196
- $sql = "SELECT * FROM $wplc_webhook_table ";
197
-
198
- if($where!==""){
199
- $results = $wpdb->get_results($wpdb->prepare($sql.$where,intval($id)));
200
- }else {
201
- $results = $wpdb->get_results($sql);
202
- }
203
-
204
- if($wpdb->num_rows){
205
- return $results;
206
- } else {
207
- return false;
208
- }
209
  }
210
 
211
  /*
212
  * Return specific webhook data
213
  */
214
- function wplc_webhook_get_data($webhook_id){
215
- $results = wplc_webhooks_get_all_db("WHERE `id` = %d", $webhook_id);
216
- if($results !== false){
217
- return $results[0];
218
- } else {
219
- return false;
220
- }
221
  }
222
 
223
  /*
224
  * Return all matched webhook
225
  */
226
- function wplc_webhook_get_matched_hooks($event_code){
227
- $results = wplc_webhooks_get_all_db("WHERE `action` = %d", $event_code);
228
- if($results !== false){
229
- return $results;
230
- } else {
231
- return false;
232
- }
233
  }
234
 
235
  /*
236
  * Renders webhooks table
237
  */
238
  function wplc_webhooks_table() {
239
- global $wpdb, $wplc_webhook_table, $wplc_webhook_events;
240
- $webhooks = wplc_webhooks_get_all_db();
241
-
242
- $content = "";
243
- if($webhooks !== false){
244
-
245
- $content .= "<table id='webhooks' class='wp-list-table wplc_list_table widefat' cellspacing='0' width='100%'>";
246
- $content .= "<thead>";
247
- $content .= "<tr>";
248
- $content .= "<th scope='col' id='event' style='width:30%;'><span>".__("Event",'wp-live-chat-support')."</span></th>";
249
- $content .= "<th scope='col' id='target' style='width:30%;'><span>".__("Target URL",'wp-live-chat-support')."</span></th>";
250
- $content .= "<th scope='col' id='method' style='width:10%;'><span>".__("Method",'wp-live-chat-support')."</span></th>";
251
- $content .= "<th scope='col' id='action'><span>".__("Action",'wp-live-chat-support')."</span></th>";
252
- $content .= "</tr>";
253
- $content .= "</thead>";
254
- $content .= "<tbody>";
255
-
256
- foreach ($webhooks as $key => $webhook) {
257
- $content .= "<tr>";
258
- $content .= "<td>". $wplc_webhook_events[$webhook->action] ."</td>";
259
- $content .= "<td>". $webhook->url ."</td>";
260
- $content .= "<td>". $webhook->method ."</td>";
261
- $content .= "<td>";
262
- $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=edit_webhook&id=".$webhook->id."' title='" . __("Edit", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Edit", 'wp-live-chat-support') . "</a> ";
263
- $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=delete_webhook&id=".$webhook->id."' title='" . __("Delete", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Delete", 'wp-live-chat-support') . "</a>";
264
- $content .= "</td>";
265
- $content .= "</tr>";
266
- }
267
-
268
- $content .= "</tbody>";
269
- $content .= "</table>";
270
- } else {
271
- $content .= "<p class='notice notice-error' style='max-width:300px'>" . __("No Webhooks", 'wp-live-chat-support') . "</p>";
272
  }
273
 
274
- return $content;
 
 
 
 
 
 
275
  }
276
 
277
 
@@ -279,58 +279,58 @@ function wplc_webhooks_table() {
279
  * Renders webhooks add webhook form
280
  */
281
  function wplc_webhooks_add_form($force_edit = false, $webhook_id = false) {
282
- $event_value = 0;
283
- $url_value = "";
284
- $method_value = "GET";
285
-
286
- $wplc_webhook_nonce = wp_create_nonce('wplc_webhook_nonce');
287
-
288
- if($force_edit && $webhook_id !== false){
289
- $webhook_id = intval($webhook_id);
290
- $webhook_data = wplc_webhook_get_data($webhook_id);
291
- if($webhook_data !== false){
292
- $event_value = $webhook_data->action;
293
- $url_value = $webhook_data->url;
294
- $method_value = $webhook_data->method;
295
- }
296
- }
297
-
298
- $content = "<form method='POST' action='?page=wplivechat-menu-webhooks-page'>";
299
- $content .= "<table class='wp-list-table wplc_list_table widefat striped'>";
300
- $content .= "<tr>";
301
- $content .= "<td>" . __("Event", 'wp-live-chat-support') . "</td>";
302
- $content .= "<td>" . wplc_webhook_render_event_selection_dropdown("add_webhook_event", $event_value, 'width:200px') . "</td>";
303
- $content .= "</tr>";
304
-
305
- $content .= "<tr>";
306
- $content .= "<td>" . __("Target URL", 'wp-live-chat-support') . "</td>";
307
- $content .= "<td><input placeholder='http://example.com/webhook_handler' name='add_webhook_domain' value='".$url_value."' type='text' style='width:200px'></td>";
308
- $content .= "</tr>";
309
 
310
- $content .= "<tr>";
311
- $content .= "<td>" . __("Method", 'wp-live-chat-support') . "</td>";
312
- $content .= "<td>";
313
- $content .= "<select id='add_webhook_method' name='add_webhook_method' style='width:200px' value='".$method_value."'>";
314
- $content .= "<option value='GET' ".($method_value === "GET" ? "selected" : "").">" . __("GET", 'wp-live-chat-support') . "</option>";
315
- $content .= "<option value='POST' ".($method_value === "POST" ? "selected" : "").">" . __("POST", 'wp-live-chat-support') . "</option>";
316
- $content .= "</select>";
317
- $content .= "</td>";
318
- $content .= "</tr>";
319
-
320
- $content .= "<tr>";
321
- $content .= "<td><input type='submit' name='".($force_edit ? "edit_webhook" : "add_webhook")."' value='" . ($force_edit ? __("Save Changes", 'wp-live-chat-support') : __("Add New", 'wp-live-chat-support') ) . "' class='button button-primary'></td>";
322
- $content .= "<td>" . ($force_edit ? "<input type='hidden' name='edit_webhook_id' value='" . $webhook_id . "' >" : "") . "</td>";
323
- $content .= "</tr>";
324
 
325
- $content .= "</table>";
326
- $content .= "<input name='wplc_webhook_nonce' type='hidden' value='" . $wplc_webhook_nonce ."' >";
327
- $content .= "</form>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
329
- return $content;
330
  }
331
 
332
  function wplc_webhooks_confirm_delete_prompt() {
333
- $id=intval($_GET['id']);
334
  $wplc_webhook_nonce = wp_create_nonce('wplc_webhook_nonce');
335
  $content = "<table class='wp-list-table wplc_list_table widefat striped' style='max-width:350px'>";
336
  $content .= "<tr>";
@@ -338,7 +338,7 @@ function wplc_webhooks_confirm_delete_prompt() {
338
  $content .= "</tr>";
339
  $content .= "<tr>";
340
  $content .= "<td>";
341
- $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=delete_webhook_confirmed&id=".$id."&wplc_webhook_nonce=" . $wplc_webhook_nonce ."' title='" . __("Confirm", 'wp-live-chat-support') . "' class='button button-primary'>" . __("Confirm", 'wp-live-chat-support') . "</a> ";
342
  $content .= "<a href='?page=wplivechat-menu-webhooks-page' title='" . __("Cancel", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Cancel", 'wp-live-chat-support') . "</a> ";
343
  $content .= "</td>";
344
  $content .= "</tr>";
@@ -346,126 +346,127 @@ function wplc_webhooks_confirm_delete_prompt() {
346
  return $content;
347
  }
348
 
349
- function wplc_webhook_render_event_selection_dropdown($name, $selected = 0, $styles = ''){
350
- global $wplc_webhook_events;
351
 
352
- $content = "<select id='$name' name='$name' style='$styles'>";
353
- foreach ($wplc_webhook_events as $key => $value) {
354
- $content .= "<option value='$key' ".(intval($key) === intval($selected) ? "selected " : "" ).">" . $value . "</option>";
355
- }
356
- $content .= "</select>";
357
 
358
- return $content;
359
  }
360
 
361
  add_action("wplc_fire_webhook", "wplc_webhook_send", 10, 2);
362
  /*
363
  * Sends the payload to any matched events - Magic
364
  */
365
- function wplc_webhook_send($event_code, $payload){
366
- global $wplc_webhook_events;
367
- if(isset($event_code) && isset($payload)){
368
- $event_code = intval($event_code);
369
- if(array_key_exists($event_code, $wplc_webhook_events)){
370
- $matches = wplc_webhook_get_matched_hooks(intval($event_code));
371
- if($matches !== false){
372
- //fire off the hooks
373
- $error_found = false;
374
- foreach ($matches as $webhook) {
375
- $target_url = isset($webhook->url) ? $webhook->url : false;
376
- $method = isset($webhook->method) && $webhook->method === "GET" ? "GET" : "POST";
377
-
378
- if(!is_array($payload)){
379
- //Not an array, no worries we will fix that
380
- $payload = array("other" => $payload);
381
- }
382
-
383
- $payload = array(
384
- "event" => $wplc_webhook_events[intval($event_code)],
385
- "data" => json_encode($payload),
386
- "time_sent" => time()
387
- );
388
-
389
- if($target_url !== false && $target_url !== ""){
390
- $result = "";
391
- if($method === "POST"){
392
- /** Replaced with WP HTTP API Calls */
393
-
394
- $response = wp_remote_post( $target_url, array(
395
- 'method' => 'POST',
396
- 'timeout' => 45,
397
- 'redirection' => 5,
398
- 'httpversion' => '1.0',
399
- 'blocking' => true,
400
- 'headers' => array(),
401
- 'body' => $payload,
402
- 'cookies' => array()
403
- )
404
- );
405
-
406
- if ( is_wp_error( $response ) ) {
407
- //This has failed
408
- $error_found = true;
409
- $result = "Failed! No Response.";
410
- }
411
- } else {
412
- /** Replaced with WP HTTP API Calls */
413
-
414
- $get_data = http_build_query($payload);
415
- $response = wp_remote_get($target_url."?".$get_data);
416
- if ( is_wp_error( $response ) ) {
417
- //This has failed
418
- $error_found = true;
419
- $result = "Failed! No Response.";
420
- }
421
- }
422
- }
423
- }
424
  }
 
425
  }
 
426
  }
 
427
  }
428
 
429
  add_action("wplc_change_chat_status_hook", "wplc_webhook_status_change_monitor", 10, 2);
430
  /*
431
- * Special delegate function for status changes
432
- */
433
- function wplc_webhook_status_change_monitor($cid, $status){
434
- switch (intval($status)) {
435
- case 2:
436
- //Chat Request
437
- do_action("wplc_fire_webhook", 4, array("chat_id" => $cid));
438
- break;
439
- case 3:
440
- //Agent Accept
441
- do_action("wplc_fire_webhook", 5, array("chat_id" => $cid));
442
- break;
443
- }
444
  }
445
 
446
  add_action("wplc_log_user_on_page_after_hook", "wplc_webhook_new_visitor_monitor", 10, 2);
447
  /*
448
  * Special Delegate function for new visitor (log user on page)
449
  */
450
- function wplc_webhook_new_visitor_monitor($dbid, $wplc_session_data){
451
- do_action("wplc_fire_webhook", 3, array("chat_id" => $dbid));
452
  }
453
 
454
  add_action("wp_login", "wplc_webhook_login_monitor", 10, 2);
455
  /*
456
  * Watches all login activity to track when an agent logs in
457
  */
458
- function wplc_webhook_login_monitor($user_login, $user){
459
- if( get_user_meta( $user->ID, 'wplc_ma_agent', true ) ){
460
- //Is an agent
461
- do_action("wplc_fire_webhook", 0, array("agent_id" => $user->ID));
462
- }
463
  }
464
 
465
  add_action("wplc_hook_admin_settings_save", "wplc_webhook_save_settings_monitor");
466
  /*
467
  * Checks when settings are saved
468
  */
469
- function wplc_webhook_save_settings_monitor(){
470
- do_action("wplc_fire_webhook", 6, array("user_id" => get_current_user_id()));
471
  }
1
+ <?php
2
 
3
+ if (!defined('ABSPATH')) {
4
+ exit;
5
  }
6
 
7
  global $wplc_webhook_table, $wplc_webhook_events;
8
  $wplc_webhook_table = $wpdb->prefix . "wplc_webhooks";
9
 
10
  //Use these when sending a payload
11
+ $wplc_webhook_events = array(
12
+ 0 => __("Agent Login", 'wp-live-chat-support'),
13
+ 3 => __("New Visitor", 'wp-live-chat-support'),
14
+ 4 => __("Chat Request", 'wp-live-chat-support'),
15
+ 5 => __("Agent Accept", 'wp-live-chat-support'),
16
+ 6 => __("Settings Changed", 'wp-live-chat-support')
17
+ );
18
 
19
  add_action("wplc_activate_hook", "wplc_webhook_db_setup", 10);
20
  add_action("wplc_update_hook", "wplc_webhook_db_setup", 10);
21
  /*
22
  * Updates/Creates the required tables in order to use devices on node
23
  */
24
+ function wplc_webhook_db_setup() {
25
+ global $wplc_webhook_table;
26
 
27
+ $wplc_webhooks_sql = "
28
  CREATE TABLE " . $wplc_webhook_table . " (
29
  id int(11) NOT NULL AUTO_INCREMENT,
30
  url varchar(700) NULL,
34
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
35
  ";
36
 
37
+ dbDelta($wplc_webhooks_sql);
38
  }
39
 
40
+ add_action("wplc_hook_menu_mid", "wplc_webhooks_manager_menu", 11, 1);
41
  /*
42
  * Adds a Webhooks menu item to admin menu
43
  */
44
  function wplc_webhooks_manager_menu($cap) {
45
+ $wplc_settings = wplc_get_options();
46
+ if ($wplc_settings['wplc_use_node_server']) {
47
+ //Only add this menu item if user is using node.
48
+ if (current_user_can("manage_options")) {
49
+ add_submenu_page('wplivechat-menu', __('Webhooks', 'wp-live-chat-support'), __('Webhooks', 'edit_posts'), $cap[0], 'wplivechat-menu-webhooks-page', 'wplc_webhooks_page');
 
50
  }
51
+ }
52
  }
53
 
54
  /*
55
  * Draws the webhooks page
56
  */
57
+ function wplc_webhooks_page() {
58
+ wplc_webhook_header_check();
59
 
60
+ $add_webhook_btn = isset($_GET["wplc_action"]) && $_GET["wplc_action"] !== "delete_webhook_confirmed" ? "" : "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=add_webhook' class='button button-secondary'>" . __("Add New", 'wp-livechat') . "</a>";
61
 
62
+ $content = "<div class='wrap wplc_wrap'>";
63
+ $content .= "<h2>" . __('Web Hooks', 'wp-live-chat-support') . " " . $add_webhook_btn . "</h2>";
64
 
65
+ if (isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'add_webhook') {
66
+ $content .= wplc_webhooks_add_form();
67
+ } else if (isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'edit_webhook') {
68
+ $content .= wplc_webhooks_add_form(true, $_GET['id']);
69
+ } else if (isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'delete_webhook') {
70
+ $content .= wplc_webhooks_confirm_delete_prompt();
71
+ } else {
72
+ $content .= wplc_webhooks_table();
73
+ }
74
+
75
+ $content .= "</div>"; //Close Wrap
 
76
 
77
+
78
+ echo $content;
79
  }
80
 
81
+ function wplc_webhook_header_check() {
82
+ if (isset($_POST['add_webhook'])) {
83
+ //User is trying to add a webhook
84
+ if (wplc_webhook_add_webhook()) {
85
+ echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook created", 'wp-live-chat-support') . "</p>";
86
+ } else {
87
+ echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be created", 'wp-live-chat-support') . "</p>";
 
88
  }
89
+ }
90
 
91
+ if (isset($_POST['edit_webhook'])) {
92
+ //User is trying to edit a webhook
93
+ if (wplc_webhook_edit_webhook()) {
94
+ echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook edited", 'wp-live-chat-support') . "</p>";
95
+ } else {
96
+ echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be edited", 'wp-live-chat-support') . "</p>";
 
97
  }
98
+ }
99
 
100
+ if (isset($_GET['wplc_action']) && $_GET['wplc_action'] === 'delete_webhook_confirmed') {
101
+ if (!isset($_GET['wplc_webhook_nonce']) || !wp_verify_nonce($_GET['wplc_webhook_nonce'], 'wplc_webhook_nonce')) {
102
+ wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
103
+ }
104
 
105
+ $webhook_id = isset($_GET['id']) ? intval($_GET['id']) : false;
106
+ if ($webhook_id !== false) {
107
+ if (wplc_webhook_delete_webhook($webhook_id)) {
108
+ echo "<p class='notice notice-success' style='max-width:300px'>" . __("Webhook deleted", 'wp-live-chat-support') . "</p>";
109
+ } else {
110
+ echo "<p class='notice notice-error' style='max-width:300px'>" . __("Webhook could not be delete", 'wp-live-chat-support') . "</p>";
111
+ }
 
112
  }
113
+ }
114
  }
115
 
116
+ function wplc_webhook_add_webhook() {
117
+ global $wpdb;
118
+ global $wplc_webhook_table;
119
 
120
+ if (isset($_POST['add_webhook_event'])) {
121
+ if (!isset($_POST['wplc_webhook_nonce']) || !wp_verify_nonce($_POST['wplc_webhook_nonce'], 'wplc_webhook_nonce')) {
122
+ wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
123
+ }
124
+
125
+ $event = intval($_POST['add_webhook_event']);
126
+ $action_url = sanitize_text_field($_POST['add_webhook_domain']);
127
+ $method = isset($_POST['add_webhook_method']) ? sanitize_text_field($_POST['add_webhook_method']) : "GET";
128
 
129
+ $sql = "INSERT INTO $wplc_webhook_table SET `url` = '%s', `action` = '%s', `method` = '%s' ";
130
+ $sql = $wpdb->prepare($sql, $action_url, $event, $method);
131
+ $wpdb->query($sql);
132
+ if ($wpdb->last_error) {
133
+ return false;
 
 
 
 
 
 
 
134
  } else {
135
+ return true;
136
  }
137
+ } else {
138
+ return false;
139
+ }
140
  }
141
 
142
+ function wplc_webhook_edit_webhook() {
143
+ global $wpdb;
144
+ global $wplc_webhook_table;
145
 
146
+ $webhook_id = isset($_POST['edit_webhook_id']) ? intval($_POST['edit_webhook_id']) : false;
147
+ if (isset($_POST['add_webhook_event']) && $webhook_id !== false) {
148
+ if (!isset($_POST['wplc_webhook_nonce']) || !wp_verify_nonce($_POST['wplc_webhook_nonce'], 'wplc_webhook_nonce')) {
149
+ wp_die(__("You do not have permission do perform this action", 'wp-live-chat-support'));
150
+ }
151
 
152
+ $event = intval($_POST['add_webhook_event']);
153
+ $action_url = sanitize_text_field($_POST['add_webhook_domain']);
154
+ $method = isset($_POST['add_webhook_method']) ? sanitize_text_field($_POST['add_webhook_method']) : "GET";
155
+
156
+ $sql = "UPDATE $wplc_webhook_table SET `url` = '%s', `action` = '%s', `method` = '%s' WHERE `id` = '%d' LIMIT 1";
157
+ $sql = $wpdb->prepare($sql, $action_url, $event, $method, $webhook_id);
158
+ $wpdb->query($sql);
159
+ if ($wpdb->last_error) {
160
+ return false;
 
 
 
161
  } else {
162
+ return true;
163
  }
164
+ } else {
165
+ return false;
166
+ }
167
  }
168
 
169
+ function wplc_webhook_delete_webhook($webhook_id = false) {
170
+ global $wpdb;
171
+ global $wplc_webhook_table;
172
+
173
+ if ($webhook_id !== false) {
174
+ $sql = "DELETE FROM $wplc_webhook_table WHERE `id` = '%d' LIMIT 1";
175
+ $sql = $wpdb->prepare($sql, $webhook_id);
176
+ $wpdb->query($sql);
177
+ if ($wpdb->last_error) {
178
+ return false;
 
 
 
179
  } else {
180
+ return true;
181
  }
182
+ } else {
183
+ return false;
184
+ }
185
  }
186
 
187
  /*
188
  * Return all webhooks from database
189
  */
190
+ function wplc_webhooks_get_all_db($where = false, $id = false) {
191
+ global $wpdb;
192
+ global $wplc_webhook_table;
193
+
194
+ $where = ($where === false) ? "" : $where;
195
+
196
+ $sql = "SELECT * FROM $wplc_webhook_table ";
197
+
198
+ if ($where !== "") {
199
+ $results = $wpdb->get_results($wpdb->prepare($sql . $where, intval($id)));
200
+ } else {
201
+ $results = $wpdb->get_results($sql);
202
+ }
203
+
204
+ if ($wpdb->num_rows) {
205
+ return $results;
206
+ } else {
207
+ return false;
208
+ }
209
  }
210
 
211
  /*
212
  * Return specific webhook data
213
  */
214
+ function wplc_webhook_get_data($webhook_id) {
215
+ $results = wplc_webhooks_get_all_db("WHERE `id` = %d", $webhook_id);
216
+ if ($results !== false) {
217
+ return $results[0];
218
+ } else {
219
+ return false;
220
+ }
221
  }
222
 
223
  /*
224
  * Return all matched webhook
225
  */
226
+ function wplc_webhook_get_matched_hooks($event_code) {
227
+ $results = wplc_webhooks_get_all_db("WHERE `action` = %d", $event_code);
228
+ if ($results !== false) {
229
+ return $results;
230
+ } else {
231
+ return false;
232
+ }
233
  }
234
 
235
  /*
236
  * Renders webhooks table
237
  */
238
  function wplc_webhooks_table() {
239
+ global $wpdb, $wplc_webhook_table, $wplc_webhook_events;
240
+ $webhooks = wplc_webhooks_get_all_db();
241
+
242
+ $content = "";
243
+ if ($webhooks !== false) {
244
+
245
+ $content .= "<table id='webhooks' class='wp-list-table wplc_list_table widefat' cellspacing='0' width='100%'>";
246
+ $content .= "<thead>";
247
+ $content .= "<tr>";
248
+ $content .= "<th scope='col' id='event' style='width:30%;'><span>" . __("Event", 'wp-live-chat-support') . "</span></th>";
249
+ $content .= "<th scope='col' id='target' style='width:30%;'><span>" . __("Target URL", 'wp-live-chat-support') . "</span></th>";
250
+ $content .= "<th scope='col' id='method' style='width:10%;'><span>" . __("Method", 'wp-live-chat-support') . "</span></th>";
251
+ $content .= "<th scope='col' id='action'><span>" . __("Action", 'wp-live-chat-support') . "</span></th>";
252
+ $content .= "</tr>";
253
+ $content .= "</thead>";
254
+ $content .= "<tbody>";
255
+
256
+ foreach ($webhooks as $key => $webhook) {
257
+ $content .= "<tr>";
258
+ $content .= "<td>" . $wplc_webhook_events[$webhook->action] . "</td>";
259
+ $content .= "<td>" . $webhook->url . "</td>";
260
+ $content .= "<td>" . $webhook->method . "</td>";
261
+ $content .= "<td>";
262
+ $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=edit_webhook&id=" . $webhook->id . "' title='" . __("Edit", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Edit", 'wp-live-chat-support') . "</a> ";
263
+ $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=delete_webhook&id=" . $webhook->id . "' title='" . __("Delete", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Delete", 'wp-live-chat-support') . "</a>";
264
+ $content .= "</td>";
265
+ $content .= "</tr>";
 
 
 
 
 
 
266
  }
267
 
268
+ $content .= "</tbody>";
269
+ $content .= "</table>";
270
+ } else {
271
+ $content .= "<p class='notice notice-error' style='max-width:300px'>" . __("No Webhooks", 'wp-live-chat-support') . "</p>";
272
+ }
273
+
274
+ return $content;
275
  }
276
 
277
 
279
  * Renders webhooks add webhook form
280
  */
281
  function wplc_webhooks_add_form($force_edit = false, $webhook_id = false) {
282
+ $event_value = 0;
283
+ $url_value = "";
284
+ $method_value = "GET";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
 
286
+ $wplc_webhook_nonce = wp_create_nonce('wplc_webhook_nonce');
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
+ if ($force_edit && $webhook_id !== false) {
289
+ $webhook_id = intval($webhook_id);
290
+ $webhook_data = wplc_webhook_get_data($webhook_id);
291
+ if ($webhook_data !== false) {
292
+ $event_value = $webhook_data->action;
293
+ $url_value = $webhook_data->url;
294
+ $method_value = $webhook_data->method;
295
+ }
296
+ }
297
+
298
+ $content = "<form method='POST' action='?page=wplivechat-menu-webhooks-page'>";
299
+ $content .= "<table class='wp-list-table wplc_list_table widefat striped'>";
300
+ $content .= "<tr>";
301
+ $content .= "<td>" . __("Event", 'wp-live-chat-support') . "</td>";
302
+ $content .= "<td>" . wplc_webhook_render_event_selection_dropdown("add_webhook_event", $event_value, 'width:200px') . "</td>";
303
+ $content .= "</tr>";
304
+
305
+ $content .= "<tr>";
306
+ $content .= "<td>" . __("Target URL", 'wp-live-chat-support') . "</td>";
307
+ $content .= "<td><input placeholder='http://example.com/webhook_handler' name='add_webhook_domain' value='" . $url_value . "' type='text' style='width:200px'></td>";
308
+ $content .= "</tr>";
309
+
310
+ $content .= "<tr>";
311
+ $content .= "<td>" . __("Method", 'wp-live-chat-support') . "</td>";
312
+ $content .= "<td>";
313
+ $content .= "<select id='add_webhook_method' name='add_webhook_method' style='width:200px' value='" . $method_value . "'>";
314
+ $content .= "<option value='GET' " . ($method_value === "GET" ? "selected" : "") . ">" . __("GET", 'wp-live-chat-support') . "</option>";
315
+ $content .= "<option value='POST' " . ($method_value === "POST" ? "selected" : "") . ">" . __("POST", 'wp-live-chat-support') . "</option>";
316
+ $content .= "</select>";
317
+ $content .= "</td>";
318
+ $content .= "</tr>";
319
+
320
+ $content .= "<tr>";
321
+ $content .= "<td><input type='submit' name='" . ($force_edit ? "edit_webhook" : "add_webhook") . "' value='" . ($force_edit ? __("Save Changes", 'wp-live-chat-support') : __("Add New", 'wp-live-chat-support')) . "' class='button button-primary'></td>";
322
+ $content .= "<td>" . ($force_edit ? "<input type='hidden' name='edit_webhook_id' value='" . $webhook_id . "' >" : "") . "</td>";
323
+ $content .= "</tr>";
324
+
325
+ $content .= "</table>";
326
+ $content .= "<input name='wplc_webhook_nonce' type='hidden' value='" . $wplc_webhook_nonce . "' >";
327
+ $content .= "</form>";
328
 
329
+ return $content;
330
  }
331
 
332
  function wplc_webhooks_confirm_delete_prompt() {
333
+ $id = intval($_GET['id']);
334
  $wplc_webhook_nonce = wp_create_nonce('wplc_webhook_nonce');
335
  $content = "<table class='wp-list-table wplc_list_table widefat striped' style='max-width:350px'>";
336
  $content .= "<tr>";
338
  $content .= "</tr>";
339
  $content .= "<tr>";
340
  $content .= "<td>";
341
+ $content .= "<a href='?page=wplivechat-menu-webhooks-page&wplc_action=delete_webhook_confirmed&id=" . $id . "&wplc_webhook_nonce=" . $wplc_webhook_nonce . "' title='" . __("Confirm", 'wp-live-chat-support') . "' class='button button-primary'>" . __("Confirm", 'wp-live-chat-support') . "</a> ";
342
  $content .= "<a href='?page=wplivechat-menu-webhooks-page' title='" . __("Cancel", 'wp-live-chat-support') . "' class='button button-secondary'>" . __("Cancel", 'wp-live-chat-support') . "</a> ";
343
  $content .= "</td>";
344
  $content .= "</tr>";
346
  return $content;
347
  }
348
 
349
+ function wplc_webhook_render_event_selection_dropdown($name, $selected = 0, $styles = '') {
350
+ global $wplc_webhook_events;
351
 
352
+ $content = "<select id='$name' name='$name' style='$styles'>";
353
+ foreach ($wplc_webhook_events as $key => $value) {
354
+ $content .= "<option value='$key' " . (intval($key) === intval($selected) ? "selected " : "") . ">" . $value . "</option>";
355
+ }
356
+ $content .= "</select>";
357
 
358
+ return $content;
359
  }
360
 
361
  add_action("wplc_fire_webhook", "wplc_webhook_send", 10, 2);
362
  /*
363
  * Sends the payload to any matched events - Magic
364
  */
365
+ function wplc_webhook_send($event_code, $payload) {
366
+ global $wplc_webhook_events;
367
+ if (isset($event_code) && isset($payload)) {
368
+ $event_code = intval($event_code);
369
+ if (array_key_exists($event_code, $wplc_webhook_events)) {
370
+ $matches = wplc_webhook_get_matched_hooks(intval($event_code));
371
+ if ($matches !== false) {
372
+ //fire off the hooks
373
+ $error_found = false;
374
+ foreach ($matches as $webhook) {
375
+ $target_url = isset($webhook->url) ? $webhook->url : false;
376
+ $method = isset($webhook->method) && $webhook->method === "GET" ? "GET" : "POST";
377
+
378
+ if (!is_array($payload)) {
379
+ //Not an array, no worries we will fix that
380
+ $payload = array("other" => $payload);
381
+ }
382
+
383
+ $payload = array(
384
+ "event" => $wplc_webhook_events[intval($event_code)],
385
+ "data" => json_encode($payload),
386
+ "time_sent" => time()
387
+ );
388
+
389
+ if ($target_url !== false && $target_url !== "") {
390
+ $result = "";
391
+ if ($method === "POST") {
392
+ /** Replaced with WP HTTP API Calls */
393
+
394
+ $response = wp_remote_post(
395
+ $target_url,
396
+ array(
397
+ 'method' => 'POST',
398
+ 'timeout' => 45,
399
+ 'redirection' => 5,
400
+ 'httpversion' => '1.0',
401
+ 'blocking' => true,
402
+ 'headers' => array(),
403
+ 'body' => $payload,
404
+ 'cookies' => array()
405
+ )
406
+ );
407
+
408
+ if (is_wp_error($response)) {
409
+ //This has failed
410
+ $error_found = true;
411
+ $result = "Failed! No Response.";
412
+ }
413
+ } else {
414
+ /** Replaced with WP HTTP API Calls */
415
+
416
+ $get_data = http_build_query($payload);
417
+ $response = wp_remote_get($target_url . "?" . $get_data);
418
+ if (is_wp_error($response)) {
419
+ //This has failed
420
+ $error_found = true;
421
+ $result = "Failed! No Response.";
422
+ }
 
423
  }
424
+ }
425
  }
426
+ }
427
  }
428
+ }
429
  }
430
 
431
  add_action("wplc_change_chat_status_hook", "wplc_webhook_status_change_monitor", 10, 2);
432
  /*
433
+ * Special delegate function for status changes
434
+ */
435
+ function wplc_webhook_status_change_monitor($cid, $status) {
436
+ switch (intval($status)) {
437
+ case 2:
438
+ //Chat Request
439
+ do_action("wplc_fire_webhook", 4, array("chat_id" => $cid));
440
+ break;
441
+ case 3:
442
+ //Agent Accept
443
+ do_action("wplc_fire_webhook", 5, array("chat_id" => $cid));
444
+ break;
445
+ }
446
  }
447
 
448
  add_action("wplc_log_user_on_page_after_hook", "wplc_webhook_new_visitor_monitor", 10, 2);
449
  /*
450
  * Special Delegate function for new visitor (log user on page)
451
  */
452
+ function wplc_webhook_new_visitor_monitor($dbid, $wplc_session_data) {
453
+ do_action("wplc_fire_webhook", 3, array("chat_id" => $dbid));
454
  }
455
 
456
  add_action("wp_login", "wplc_webhook_login_monitor", 10, 2);
457
  /*
458
  * Watches all login activity to track when an agent logs in
459
  */
460
+ function wplc_webhook_login_monitor($user_login, $user) {
461
+ if (wplc_user_is_agent($user->ID)) {
462
+ do_action("wplc_fire_webhook", 0, array("agent_id" => $user->ID));
463
+ }
 
464
  }
465
 
466
  add_action("wplc_hook_admin_settings_save", "wplc_webhook_save_settings_monitor");
467
  /*
468
  * Checks when settings are saved
469
  */
470
+ function wplc_webhook_save_settings_monitor() {
471
+ do_action("wplc_fire_webhook", 6, array("user_id" => get_current_user_id()));
472
  }
readme.txt CHANGED
@@ -1,11 +1,13 @@
1
  === WP-Live Chat by 3CX ===
2
- Contributors: WP-LiveChat, wordpress3cx
3
  Tags: live chat, live support, chat plugin, live help, wordpress live chat, chat, live chat plugin, live support plugin, live chat support plugin, chat plugin, support plugin, live help
4
- Requires at least: 4.4
5
  Tested up to: 5.2.4
6
  Requires PHP: 5.3
7
- Stable tag: 8.1.2
8
  License: GPLv2
 
 
9
 
10
  Chat with your website visitors in real-time for free! Engage with your customers and increase sales.
11
 
@@ -56,7 +58,6 @@ Connect with your website visitors for free with the WP-Live Chat plugin by 3CX.
56
  * Include/exclude the live chat from appearing on certain pages
57
  * Choose when to accept chats
58
 
59
-
60
  Get [WP-Live Chat by 3CX](https://www.3cx.com/wp-live-chat/) for free!
61
 
62
  = 30 second live chat installation =
@@ -185,6 +186,19 @@ Huge update with over 300 changes that include: Bugfixes, Vulnerability Fixes &
185
 
186
  == Changelog ==
187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  = 8.1.2 - 2019-10-24
189
  * New feature: improved auto pop-up feature, now 3 options to choose from
190
  * New feature: Pop-up only when agents are online
1
  === WP-Live Chat by 3CX ===
2
+ Contributors: WP-LiveChat, wordpress3cx, wp3cx
3
  Tags: live chat, live support, chat plugin, live help, wordpress live chat, chat, live chat plugin, live support plugin, live chat support plugin, chat plugin, support plugin, live help
4
+ Requires at least: 4.6
5
  Tested up to: 5.2.4
6
  Requires PHP: 5.3
7
+ Stable tag: 8.1.3
8
  License: GPLv2
9
+ License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
+ Text Domain: wp-live-chat-support
11
 
12
  Chat with your website visitors in real-time for free! Engage with your customers and increase sales.
13
 
58
  * Include/exclude the live chat from appearing on certain pages
59
  * Choose when to accept chats
60
 
 
61
  Get [WP-Live Chat by 3CX](https://www.3cx.com/wp-live-chat/) for free!
62
 
63
  = 30 second live chat installation =
186
 
187
  == Changelog ==
188
 
189
+ = 8.1.3 - 2019-10-31
190
+ * Bugfix: Admin detected as an agent - doesn't show offline messages form
191
+ * Bugfix: Remove picture from chat box doesn't work properly
192
+ * Bugfix: Edge JS compatibility issue in dashboard has been fixed
193
+ * Bugfix: The page will no longer refresh upon ending a chat with an agent.
194
+ * New feature: Agent online/offline switch in Wordpress admin bar
195
+ * New feature: Adjustable chatbox height 30% - 80% of page size
196
+ * Improvement: Cleaned up async_storage functions
197
+ * Improvement: Better alignment for chat popup with no picture
198
+ * Improvement: Reworked agent online/offline functions
199
+ * Improvement: Default business hours are now 9:00 - 18:00 instead of 00:00 - 00:00
200
+ * Improvement: The 'Use Logged In User Details' feature has been moved to the 'Chat Box' settings page
201
+
202
  = 8.1.2 - 2019-10-24
203
  * New feature: improved auto pop-up feature, now 3 options to choose from
204
  * New feature: Pop-up only when agents are online
wp-live-chat-support.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP-Live Chat by 3CX
4
  Plugin URI: https://www.3cx.com/wp-live-chat/
5
  Description: The easiest to use website live chat plugin. Let your visitors chat with you and increase sales conversion rates with WP-Live Chat by 3CX.
6
- Version: 8.1.2
7
  Author: 3CX
8
  Author URI: https://www.3cx.com/wp-live-chat/
9
  Domain Path: /languages
@@ -12,6 +12,19 @@
12
  */
13
 
14
  /*
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  = 8.1.2 - 2019-10-24
16
  * New feature: improved auto pop-up feature, now 3 options to choose from
17
  * New feature: Pop-up only when agents are online
@@ -377,15 +390,16 @@ function wplc_set_defaults() {
377
  'wplc_avatar_source' => '',
378
  'wplc_bh_enable' => false,
379
  'wplc_bh_interval' => 0,
380
- 'wplc_bh_hours_start' => 0,
381
  'wplc_bh_minutes_start' => 0,
382
- 'wplc_bh_hours_end' => 0,
383
  'wplc_bh_minutes_end' => 0,
384
  'wplc_chat_delay' => 2,
385
  'wplc_chat_icon' => plugins_url( '/', __FILE__ ).'images/chaticon.png',
386
  'wplc_chat_logo' => '',
387
  'wplc_chat_name' => __( 'Admin', 'wp-live-chat-support'),
388
  'wplc_chat_pic' => plugins_url( '/', __FILE__ ).'images/picture-for-chat-box.jpg',
 
389
  'wplc_close_btn_text' => __("close", 'wp-live-chat-support'),
390
  'wplc_default_department' => -1,
391
  'wplc_delay_between_loops' => 500,
@@ -611,6 +625,7 @@ add_action('wp_ajax_wplc_a2a_dismiss', 'wplc_action_callback');
611
  add_action('activated_plugin', 'wplc_redirect_on_activate');
612
  add_action('wp_ajax_wplc_choose_accepting','wplc_action_callback');
613
  add_action('wp_ajax_wplc_choose_not_accepting','wplc_action_callback');
 
614
  add_action('wplc_hook_action_callback','wplc_choose_hook_control_action_callback');
615
  add_action('wplc_hook_admin_menu_layout_display_top','wplc_ma_hook_control_admin_meny_layout_display_top');
616
  add_action('edit_user_profile_update', 'wplc_maa_set_user_as_agent');
@@ -686,19 +701,16 @@ function wplc_uninstall() {
686
  $admins->remove_cap('wplc_ma_agent');
687
  }
688
 
689
- $users = get_users(array('meta_key' => 'wplc_ma_agent'));
690
- if($users){
691
- foreach($users as $user) {
692
- delete_user_meta( $user->ID, 'wplc_user_department' );
693
- delete_user_meta( $user->ID, 'wplc_ma_agent' );
694
- delete_user_meta( $user->ID, 'wplc_user_bio' );
695
- delete_user_meta( $user->ID, 'wplc_user_facebook' );
696
- delete_user_meta( $user->ID, 'wplc_user_linkedin' );
697
- delete_user_meta( $user->ID, 'wplc_user_tagline' );
698
- delete_user_meta( $user->ID, 'wplc_user_twitter' );
699
- }
700
- }
701
-
702
  }
703
  }
704
 
@@ -789,7 +801,7 @@ function wplc_version_control() {
789
 
790
  $uid = get_current_user_id();
791
  update_user_meta($uid, 'wplc_ma_agent', 1);
792
- update_user_meta($uid, "wplc_chat_agent_online", time());
793
 
794
  /* add caps to admin */
795
  if (current_user_can('manage_options')) {
@@ -916,8 +928,10 @@ function wplc_action_callback() {
916
  ));
917
  } else if ($_POST['action'] == "wplc_admin_set_transient") {
918
  do_action("wplc_hook_set_transient");
 
919
  } else if ($_POST['action'] == "wplc_admin_remove_transient") {
920
  do_action("wplc_hook_remove_transient");
 
921
  } else if ($_POST['action'] == 'wplc_hide_ftt') {
922
  update_option("WPLC_FIRST_TIME_TUTORIAL",true);
923
  }
@@ -990,34 +1004,23 @@ function wplc_metric_dashboard_redirect(){
990
  }
991
 
992
  function wplc_admin_menu() {
 
 
 
 
 
 
 
993
 
994
- $cap = apply_filters("wplc_ma_filter_menu_control",array());
995
-
996
- $wplc_current_user = get_current_user_id();
997
-
998
- /* If user is either an agent or an admin, access the page. */
999
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) || current_user_can("wplc_ma_agent")){
1000
- $wplc_mainpage = add_menu_page('WP Live Chat', __('Live Chat', 'wp-live-chat-support'), $cap[0], 'wplivechat-menu', 'wplc_admin_menu_layout', 'dashicons-format-chat');
1001
- add_submenu_page('wplivechat-menu', __('Dashboard', 'wp-live-chat-support'), __('Dashboard', 'wp-live-chat-support'), $cap[1], 'wplivechat-menu-dashboard', 'wplc_admin_dashboard_layout');
1002
- add_submenu_page('wplivechat-menu', __('Settings', 'wp-live-chat-support'), __('Settings', 'wp-live-chat-support'), $cap[1], 'wplivechat-menu-settings', 'wplc_admin_settings_layout');
1003
- }
1004
-
1005
-
1006
- /* only if user is both an agent and an admin that has the cap assigned, can they access these pages */
1007
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) && current_user_can("wplc_ma_agent")){
1008
-
1009
- add_submenu_page('wplivechat-menu', __('History', 'wp-live-chat-support'), __('History', 'wp-live-chat-support'), $cap[2], 'wplivechat-menu-history', 'wplc_admin_history_layout');
1010
- add_submenu_page('wplivechat-menu', __('Missed Chats', 'wp-live-chat-support'), __('Missed Chats', 'wp-live-chat-support'), $cap[3], 'wplivechat-menu-missed-chats', 'wplc_admin_missed_chats');
1011
-
1012
-
1013
- add_submenu_page('wplivechat-menu', __('Offline Messages', 'wp-live-chat-support'), __('Offline Messages', 'wp-live-chat-support'), $cap[4], 'wplivechat-menu-offline-messages', 'wplc_admin_offline_messages');
1014
-
1015
- do_action("wplc_hook_menu_mid",$cap);
1016
-
1017
-
1018
- add_submenu_page('wplivechat-menu', __('Support', 'wp-live-chat-support'), __('Support', 'wp-live-chat-support'), 'manage_options', 'wplivechat-menu-support-page', 'wplc_support_menu');
1019
- }
1020
- do_action("wplc_hook_menu");
1021
  }
1022
 
1023
 
@@ -1108,7 +1111,7 @@ function wplc_push_js_to_front() {
1108
 
1109
  if ($wplc_settings['wplc_use_node_server']) {
1110
  wp_localize_script('wplc-server-script', 'tcx_api_key', wplc_node_server_token_get());
1111
- wp_register_script('wplc-node-server-script', WPLC_PLUGIN_URL."/js/vendor/sockets.io/socket.io.slim.js", array('jquery'), WPLC_PLUGIN_VERSION);
1112
  wp_enqueue_script('wplc-node-server-script');
1113
  wp_register_script('wplc-user-events-script', plugins_url('/js/wplc_u_node_events.js', __FILE__),array('jquery', 'wplc-server-script'),WPLC_PLUGIN_VERSION);
1114
  /* Not used in front-end
@@ -1120,9 +1123,9 @@ function wplc_push_js_to_front() {
1120
 
1121
  //Emoji Libs
1122
  if (!$wplc_settings['wplc_disable_emojis']) {
1123
- wp_register_script('wplc-user-js-emoji-concat', WPLC_PLUGIN_URL."/js/vendor/wdt-emoji/wdt-emoji-concat.min.js", array("wplc-server-script", "wplc-server-script"), WPLC_PLUGIN_VERSION, false);
1124
  wp_enqueue_script('wplc-user-js-emoji-concat');
1125
- wp_register_style( 'wplc-admin-style-emoji', WPLC_PLUGIN_URL."/js/vendor/wdt-emoji/wdt-emoji-bundle.css", false, WPLC_PLUGIN_VERSION );
1126
  wp_enqueue_style( 'wplc-admin-style-emoji' );
1127
  }
1128
  wp_register_script('wplc-user-node-node-primary', plugins_url('/js/wplc_node.js', __FILE__),array('jquery', 'wplc-server-script', 'wplc-user-script'), WPLC_PLUGIN_VERSION);
@@ -1201,18 +1204,13 @@ function wplc_push_js_to_front() {
1201
  /**
1202
  * Create a JS object for all Agent ID's and Gravatar MD5's
1203
  */
1204
- $user_array = get_users(array(
1205
- 'meta_key' => 'wplc_ma_agent',
1206
- ));
1207
-
1208
  $a_array = array();
1209
- if ($user_array) {
1210
- foreach ($user_array as $user) {
1211
- $a_array[$user->ID] = array();
1212
- $a_array[$user->ID]['name'] = apply_filters( "wplc_decide_agents_name", sanitize_text_field($user->display_name), $wplc_settings );
1213
- $a_array[$user->ID]['md5'] = md5( $user->user_email );
1214
- $a_array[$user->ID]['tagline'] = get_user_meta($user->ID, 'wplc_user_tagline', true);
1215
- }
1216
  }
1217
  wp_localize_script('wplc-user-script', 'wplc_agent_data', $a_array);
1218
 
@@ -1520,7 +1518,12 @@ function wplc_filter_control_live_chat_box_html_main_div_top($wplc_settings,$log
1520
 
1521
  default:
1522
  $wplc_theme_type = "modern";
1523
- $hovercard_content = "<div class='wplc_hovercard_content_left'>".apply_filters("wplc_filter_modern_theme_hovercard_content_left","")."</div><div class='wplc_hovercard_content_right'>".apply_filters("wplc_filter_live_chat_box_html_1st_layer",wplc_filter_control_live_chat_box_html_1st_layer($wplc_settings,$logged_in,$wplc_using_locale,'wplc-color-4'))."</div>";
 
 
 
 
 
1524
  $hovercard_content = apply_filters("wplc_filter_hovercard_content", $hovercard_content);
1525
  $ret_msg .= "<div id='wplc_hovercard' style='display:none' class='".$wplc_theme_type."'>";
1526
  $ret_msg .= "<div id='wplc_hovercard_content'>".apply_filters("wplc_filter_live_chat_box_pre_layer1","").$hovercard_content."</div>";
@@ -1546,8 +1549,6 @@ function wplc_filter_control_live_chat_box_html_main_div_top($wplc_settings,$log
1546
 
1547
  add_filter("wplc_filter_modern_theme_hovercard_content_left","wplc_filter_control_modern_theme_hovercard_content_left",10,1);
1548
  function wplc_filter_control_modern_theme_hovercard_content_left($msg) {
1549
-
1550
- $msg .= "<div class='wplc_left_logo' style='background:url(".plugins_url('images/iconmicro.png', __FILE__).") no-repeat; background-size: cover;'></div>";
1551
  $msg = apply_filters("wplc_filter_microicon",$msg);
1552
  return $msg;
1553
  }
@@ -1792,11 +1793,7 @@ function wplc_filter_control_live_chat_box_html_2nd_layer($wplc_settings,$logged
1792
  }
1793
 
1794
  /* admin not logged in, show offline messages */
1795
- $wplc_offline = $wplc_default_settings_array['wplc_pro_offline1'];
1796
- $text = ($wplc_using_locale ? $wplc_offline : stripslashes($wplc_settings['wplc_pro_offline1']));
1797
-
1798
  $ret_msg = "<div id=\"wp-live-chat-2-info\" class=\"wplc-color-bg-1 wplc-color-2\">";
1799
- $ret_msg .= $text;
1800
  $ret_msg .= "</div>";
1801
  $ret_msg .= "<div id=\"wplc_message_div\">";
1802
  $ret_msg .= "<input type=\"text\" name=\"wplc_name\" id=\"wplc_name\" value=\"$wplc_loggedin_user_name\" placeholder=\"".__("Name", 'wp-live-chat-support')."\" />";
@@ -1949,27 +1946,23 @@ function wplc_filter_control_live_chat_box_html_4th_layer($wplc_settings, $wplc_
1949
  * @return string
1950
  * @since 6.0.00
1951
  */
1952
- function wplc_filter_control_live_chat_box_html_1st_layer($wplc_settings,$logged_in,$wplc_using_locale, $class_override = false) {
1953
  global $wplc_default_settings_array;
1954
  $ret_msg = "<div id='wplc_first_message'>";
1955
  if ($logged_in) {
1956
- $wplc_fst_1 = __('Questions?', 'wp-live-chat-support');
1957
- $wplc_fst_2 = __('Chat with us', 'wp-live-chat-support');
1958
  if ($wplc_settings['wplc_newtheme'] == "theme-2") {
1959
  $coltheme = "wplc-color-4";
1960
  } else {
1961
  $coltheme = "wplc-color-2";
1962
  }
1963
-
1964
- if ($class_override){
1965
  //Override color class
1966
  $coltheme = $class_override;
1967
  }
1968
- $wplc_tl_msg = "<div class='$coltheme'><strong>" . ($wplc_using_locale ? $wplc_fst_1 : stripslashes($wplc_settings['wplc_pro_fst1'])) . "</strong> " . ( $wplc_using_locale ? $wplc_fst_2 : stripslashes($wplc_settings['wplc_pro_fst2'])) ."</div>";
1969
  $ret_msg .= $wplc_tl_msg;
1970
  } else {
1971
- $wplc_na = $wplc_default_settings_array['wplc_pro_na'];
1972
- $wplc_tl_msg = "<span class='wplc_offline'>" . ($wplc_using_locale ? $wplc_na : stripslashes($wplc_settings['wplc_pro_na'])) . "</span>";
1973
  $ret_msg .= $wplc_tl_msg;
1974
  }
1975
  $ret_msg .= "</div>";
@@ -1979,7 +1972,6 @@ function wplc_filter_control_live_chat_box_html_1st_layer($wplc_settings,$logged
1979
  add_filter("wplc_loggedin_filter","wplc_filter_control_loggedin",10,1);
1980
  function wplc_filter_control_loggedin($logged_in) {
1981
  $wplc_is_admin_logged_in = get_transient("wplc_is_admin_logged_in");
1982
-
1983
  if ($wplc_is_admin_logged_in != 1) {
1984
  $logged_in = false;
1985
  } else {
@@ -1996,7 +1988,6 @@ function wplc_filter_control_loggedin($logged_in) {
1996
  if (isset($logged_in_checks['app']) && $logged_in_checks['app'] == true) { $logged_in_via_app = true; }
1997
 
1998
  $logged_in = apply_filters("wplc_final_loggedin_control",$logged_in,$logged_in_via_app);
1999
-
2000
  /* admin is using the basic version and is logged in */
2001
  if ($wplc_is_admin_logged_in) { $logged_in = true; }
2002
 
@@ -2261,8 +2252,7 @@ function wplc_admin_javascript() {
2261
  */
2262
  function wplc_admin_output_js() {
2263
  $ajax_nonce = wp_create_nonce("wplc");
2264
- $wplc_current_user = get_current_user_id();
2265
- if (get_user_meta($wplc_current_user, 'wplc_ma_agent', true)) {
2266
  $wplc_settings = wplc_get_options();
2267
  wp_register_script('wplc-admin-js', plugins_url('js/wplc_u_admin.js', __FILE__), false, WPLC_PLUGIN_VERSION, false);
2268
  wp_enqueue_script('wplc-admin-js');
@@ -2272,7 +2262,7 @@ function wplc_admin_output_js() {
2272
  wp_localize_script('wplc-admin-js', 'wplc_wav_file', $wplc_wav_file);
2273
  wp_localize_script('wplc-admin-js', 'wplc_ajax_nonce', $ajax_nonce);
2274
  wp_localize_script('wplc-admin-js', 'wplc_notification_icon', $not_icon);
2275
- wp_localize_script('wplc-admin-js', 'tcx_favico_noti', WPLC_PLUGIN_URL . 'images/tcx48px_n.png');
2276
  wp_localize_script('wplc-admin-js', 'tcx_favico', WPLC_PLUGIN_URL . 'images/tcx48px.png');
2277
  $extra_data = apply_filters("wplc_filter_admin_javascript",array());
2278
  wp_localize_script('wplc-admin-js', 'wplc_extra_data', $extra_data);
@@ -2341,106 +2331,77 @@ function wplc_filter_control_chat_dashboard_visitors_online_bottom($text) {
2341
  }
2342
 
2343
  function wplc_admin_menu_layout_display() {
2344
-
2345
- $wplc_current_user = get_current_user_id();
2346
-
2347
- if( get_user_meta( $wplc_current_user, 'wplc_ma_agent', true ) ){
2348
-
2349
- do_action("wplc_hook_admin_menu_layout_display_top");
2350
-
2351
- wplc_stats("chat_dashboard");
2352
-
2353
- if (!isset($_GET['action'])) {
2354
- ?>
2355
-
2356
- <div class='wplc_network_issue' style='display:none;'></div>
2357
-
2358
- <div class='wplc_page_title'>
2359
- <?php wplc_first_time_tutorial(); ?>
2360
-
2361
- </div>
2362
-
2363
-
2364
- <div id="wplc_sound"></div>
2365
-
2366
- <div id="wplc_admin_chat_holder">
2367
-
2368
- <div class="wplc_admin_chat_on_premise_header">
2369
-
2370
- <div class="wplc_admin_chat_on_premise_header_left">
2371
- <img src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABkAAD/4QMvaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpERkVFRTcwRUFENDkxMUU5QjUzM0I0QThEMzhGNzc5MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpERkVFRTcwRkFENDkxMUU5QjUzM0I0QThEMzhGNzc5MyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkRGRUVFNzBDQUQ0OTExRTlCNTMzQjRBOEQzOEY3NzkzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkRGRUVFNzBEQUQ0OTExRTlCNTMzQjRBOEQzOEY3NzkzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4AJkFkb2JlAGTAAAAAAQMAFQQDBgoNAAAH7QAADocAABIG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" align="middle"> <h2>WP Live Chat by 3CX</h2>
2372
- <?php do_action("wplc_hook_chat_dashboard_above"); ?>
2373
- </div>
2374
- <div id="wplc_admin_chat_info_new" class="wplc_admin_chat_on_premise_header_right">
2375
- <div class="wplc_admin_chat_on_premise_switchery_label">
2376
- <b><?php _e("Keep this window open to get notified of new chats.",'wp-live-chat-support'); ?></b>
2377
- </div>
2378
-
2379
- <div class='wplc_chat_vis_count_box'>
2380
- <?php do_action("wplc_hook_chat_dahsboard_visitors_online_top"); ?>
2381
- <div class="wplc_chat_dashboard_on_premise_stats">
2382
- <span class='wplc_vis_online'>0</span> <?php _e("Visitor(s) online",'wp-live-chat-support'); ?>
2383
- </div>
2384
- <div class="wplc_chat_dashboard_on_premise_stats">
2385
- <?php echo apply_filters("wplc_filter_chat_dahsboard_visitors_online_bottom",""); ?>
2386
- </div>
2387
- <?php do_action("wplc_after_chat_visitor_count_hook"); ?>
2388
- </div>
2389
- </div>
2390
-
2391
- </div>
2392
-
2393
- <div id="wplc_admin_chat_area_new">
2394
- <div style="display:block;">
2395
- <div class='wplc_chat_on_premise_header'>
2396
- <div class='wplc_header_vh wplc_header_v'><?php _e("Visitor",'wp-live-chat-support'); ?></div>
2397
- <div class='wplc_header_vh wplc_header_t'><?php _e("Time",'wp-live-chat-support'); ?></div>
2398
- <div class='wplc_header_vh wplc_header_nr'><?php _e("Type",'wp-live-chat-support'); ?></div>
2399
- <div class='wplc_header_vh wplc_header_dev'><?php _e("Device",'wp-live-chat-support'); ?></div>
2400
- <div class='wplc_header_vh wplc_header_d'><?php _e("Data",'wp-live-chat-support'); ?></div>
2401
- <div class='wplc_header_vh wplc_header_s'><?php _e("Status",'wp-live-chat-support'); ?></div>
2402
- <div class='wplc_header_vh wplc_header_a'><?php _e("Action",'wp-live-chat-support'); ?></div>
2403
- </div>
2404
- <div id='wplc_chat_ul'></div>
2405
-
2406
- <?php //do_action("wplc_hook_chat_dashboard_bottom"); ?>
2407
-
2408
- </div>
2409
-
2410
- </div>
2411
- </div>
2412
-
2413
-
2414
-
2415
-
2416
-
2417
- <?php
2418
- } else {
2419
- if (isset($_GET['aid'])) { $aid = intval($_GET['aid']); } else { $aid = null; }
2420
-
2421
- if (!is_null($aid)) {
2422
- do_action("wplc_hook_update_agent_id", intval($_GET['cid']), $aid);
2423
- }
2424
-
2425
- if ($_GET['action'] == 'ac') {
2426
- do_action('wplc_hook_accept_chat',$_GET, $aid);
2427
- }
2428
- do_action("wplc_hook_admin_menu_layout_display", $_GET['action'], intval($_GET['cid']), $aid);
2429
- }
2430
  } else {
2431
- ?>
2432
-
2433
- <h1><?php _e("Chat Dashboard",'wp-live-chat-support'); ?></h1>
2434
- <div id="welcome-panel" class="welcome-panel">
2435
- <div class="welcome-panel-content">
2436
- <h2><?php _e("Oh no!",'wp-live-chat-support'); ?></h2>
2437
- <p class="about-description">
2438
- <?php echo sprintf(__("You do not have access to this page as %s.",'wp-live-chat-support'),'<strong>'.__('you are not a chat agent','wp-live-chat-support').'</strong>'); ?>
2439
- </p>
2440
- </div>
2441
- </div>
2442
- <?php
2443
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
2444
  }
2445
 
2446
  add_action("wplc_hook_change_status_on_answer","wplc_hook_control_change_status_on_answer",10,2);
@@ -2714,17 +2675,12 @@ function wplc_return_admin_chat_javascript($cid) {
2714
  /**
2715
  * Create a JS object for all Agent ID's and Gravatar MD5's
2716
  */
2717
- $user_array = get_users(array(
2718
- 'meta_key' => 'wplc_ma_agent'
2719
- ));
2720
-
2721
  $a_array = array();
2722
- if ($user_array) {
2723
- foreach ($user_array as $user) {
2724
- $a_array[$user->ID] = array();
2725
- $a_array[$user->ID]['name'] = sanitize_text_field($user->display_name);
2726
- $a_array[$user->ID]['md5'] = md5( $user->user_email );
2727
- }
2728
  }
2729
  wp_localize_script('wplc-admin-chat-server', 'wplc_agent_data', $a_array);
2730
 
@@ -2864,9 +2820,9 @@ function wplc_activate() {
2864
  $wplc_settings = wplc_cleanup_old_options($wplc_settings);
2865
  update_option('WPLC_SETTINGS', $wplc_settings);
2866
  $uid = get_current_user_id();
2867
- wplc_set_agent_status($uid, true);
2868
  update_user_meta($uid, 'wplc_ma_agent', 1);
2869
- update_user_meta($uid, "wplc_chat_agent_online", time());
2870
 
2871
  $admins = get_role('administrator');
2872
  if( $admins !== null ) { $admins->add_cap('wplc_ma_agent'); }
@@ -2883,7 +2839,7 @@ function wplc_activate() {
2883
  if (!function_exists("wplc_choose_activate")) {
2884
  register_activation_hook(__FILE__, 'wplc_choose_activate');
2885
  function wplc_choose_activate( $networkwide ) {
2886
- wplc_set_agent_status(get_current_user_id(),true);
2887
  wplc_mrg_update_db( $networkwide ); //Run update db
2888
  }
2889
  }
@@ -2896,7 +2852,7 @@ if (!function_exists("wplc_choose_activate")) {
2896
  if (!function_exists("wplc_choose_deactivate")) {
2897
  register_deactivation_hook(__FILE__, 'wplc_choose_deactivate');
2898
  function wplc_choose_deactivate() {
2899
- wplc_set_agent_status(get_current_user_id(),false);
2900
  }
2901
  }
2902
 
@@ -3007,6 +2963,7 @@ function wplc_add_user_stylesheet() {
3007
  $close_icon = plugins_url('images/iconCloseRetina.png', __FILE__);
3008
 
3009
  $bg='';
 
3010
  if (!empty($wplc_settings['wplc_settings_bg'])) {
3011
  $bg = sanitize_text_field($wplc_settings['wplc_settings_bg']);
3012
  }
@@ -3016,6 +2973,9 @@ function wplc_add_user_stylesheet() {
3016
  } else {
3017
  $bg_string = "#wp-live-chat-4 { background-color: #fff; }";
3018
  }
 
 
 
3019
 
3020
  if (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ){ $icon = preg_replace('/^http:\/\//', 'https:\/\/', $icon); }
3021
  if (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ){ $close_icon = preg_replace('/^http:\/\//', 'https:\/\/', $close_icon); }
@@ -3096,15 +3056,14 @@ add_action( 'init', 'wplc_online_check_script', 10 );
3096
  * @return void
3097
  */
3098
  function wplc_online_check_script() {
3099
- if (sanitize_text_field( get_the_author_meta( 'wplc_ma_agent', get_current_user_id() ) ) == "1"){
3100
- $ajax_nonce = wp_create_nonce("wplc");
3101
- wp_register_script( 'wplc-heartbeat', plugins_url( 'js/wplc_heartbeat.js', __FILE__ ), array( 'jquery' ), WPLC_PLUGIN_VERSION, true );
3102
- wp_enqueue_script( 'wplc-heartbeat' );
3103
- wp_localize_script( 'wplc-heartbeat', 'wplc_transient_nonce', $ajax_nonce );
3104
-
3105
- $wplc_ajax_url = apply_filters("wplc_filter_ajax_url", admin_url('admin-ajax.php'));
3106
- wp_localize_script('wplc-heartbeat', 'wplc_ajaxurl', $wplc_ajax_url);
3107
- }
3108
  }
3109
 
3110
  /**
@@ -3114,13 +3073,13 @@ function wplc_online_check_script() {
3114
  add_filter( 'heartbeat_received', 'wplc_heartbeat_receive', 10, 2 );
3115
  add_filter( 'heartbeat_nopriv_received', 'wplc_heartbeat_receive', 10, 2 );
3116
  function wplc_heartbeat_receive( $response, $data ) {
3117
- if ( array_key_exists('client',$data) && $data['client'] == 'wplc_heartbeat' ) {
3118
- if (sanitize_text_field( get_the_author_meta( 'wplc_ma_agent', get_current_user_id() ) ) == "1"){
3119
- update_user_meta(get_current_user_id(), "wplc_chat_agent_online", time());
3120
- wplc_hook_control_set_transient();
3121
- }
3122
- }
3123
- return $response;
3124
  }
3125
 
3126
  /**
@@ -3606,7 +3565,7 @@ function wplc_filter_control_chat_header_extra_attr($wplc_extra_attr) {
3606
  $do_popup=false;
3607
  if ($wplc_settings['wplc_auto_pop_up']>0) {
3608
  if ($wplc_settings['wplc_auto_pop_up_online']) {
3609
- $do_popup=wplc_maa_is_agent_online();
3610
  } else {
3611
  $do_popup=true;
3612
  }
@@ -3721,6 +3680,13 @@ function wplc_head() {
3721
  $wplc_data['wplc_redirect_to_thank_you_page'] = stripslashes(sanitize_text_field(wplc_force_string($_POST, 'wplc_redirect_to_thank_you_page', $wplc_settings)));
3722
  $wplc_data['wplc_redirect_thank_you_url'] = esc_url(wplc_force_url($_POST, 'wplc_redirect_thank_you_url', $wplc_settings));
3723
  $wplc_data['wplc_disable_emojis'] = wplc_force_bool($_POST, 'wplc_disable_emojis');
 
 
 
 
 
 
 
3724
  $wplc_data['wplc_record_ip_address'] = "0";
3725
  $wplc_data['wplc_enable_msg_sound'] = wplc_force_bool($_POST, 'wplc_enable_msg_sound');
3726
  $wplc_data['wplc_enable_visitor_sound'] = wplc_force_bool($_POST, 'wplc_enable_visitor_sound');
@@ -3807,13 +3773,26 @@ function wplc_head() {
3807
  $wplc_upload_icon = wplc_force_string($_POST, 'wplc_upload_icon', '');
3808
 
3809
  if (!empty($wplc_upload_pic)) {
3810
- $wplc_data['wplc_chat_pic'] = esc_url(base64_decode($wplc_upload_pic));
 
 
 
 
3811
  }
3812
  if (!empty($wplc_upload_logo)) {
3813
- $wplc_data['wplc_chat_logo'] = esc_url(base64_decode($wplc_upload_logo));
 
 
 
 
3814
  }
3815
  if (!empty($wplc_upload_icon)) {
3816
- $wplc_data['wplc_chat_icon'] = esc_url(base64_decode($wplc_upload_icon));
 
 
 
 
 
3817
  }
3818
 
3819
  $wplc_data['wplc_chat_delay'] = wplc_force_int($_POST, 'wplc_chat_delay');
@@ -3858,24 +3837,20 @@ function wplc_head() {
3858
  if ($wplc_data['wplc_delay_between_loops'] > 1000000) { $wplc_data['wplc_delay_between_loops'] = 1000000; }
3859
 
3860
  if (isset($_POST['wplc_agent_select']) && $_POST['wplc_agent_select'] != "") {
3861
- $user_array = get_users(array(
3862
- 'meta_key' => 'wplc_ma_agent',
3863
- ));
3864
- if ($user_array) {
3865
- foreach ($user_array as $user) {
3866
- $uid = $user->ID;
3867
- $wplc_ma_user = new WP_User( $uid );
3868
- $wplc_ma_user->remove_cap( 'wplc_ma_agent' );
3869
- delete_user_meta($uid, "wplc_ma_agent");
3870
- delete_user_meta($uid, "wplc_chat_agent_online");
3871
- }
3872
  }
3873
 
3874
  $uid = intval($_POST['wplc_agent_select']);
3875
  $wplc_ma_user = new WP_User( $uid );
3876
  $wplc_ma_user->add_cap( 'wplc_ma_agent' );
3877
  update_user_meta($uid, "wplc_ma_agent", 1);
3878
- update_user_meta($uid, "wplc_chat_agent_online", time());
3879
  }
3880
 
3881
  if (isset($_POST['wplc_ban_users_ip'])) {
@@ -3917,8 +3892,6 @@ function wplc_logout() {
3917
  delete_transient('wplc_is_admin_logged_in');
3918
  }
3919
 
3920
-
3921
-
3922
  /**
3923
  * Error checks used to ensure the user's resources meet the plugin's requirements
3924
  */
@@ -4202,8 +4175,8 @@ add_action('admin_init', 'wplc_admin_download_chat_history');
4202
  * @return file
4203
  */
4204
  function wplc_admin_download_chat_history(){
4205
- if(!is_user_logged_in() || !get_user_meta(get_current_user_id(), 'wplc_ma_agent', true) ){
4206
- return;
4207
  }
4208
 
4209
  if (isset($_GET['action']) && $_GET['action'] == "download_history") {
@@ -4280,8 +4253,8 @@ function wplc_admin_download_chat_history(){
4280
  * @return void
4281
  */
4282
  function wplc_admin_download_history($type, $cid){
4283
- if(!is_user_logged_in() || !get_user_meta(get_current_user_id(), 'wplc_ma_agent', true) ){
4284
- return;
4285
  }
4286
 
4287
  global $wpdb;
@@ -4511,10 +4484,10 @@ function wplc_custom_scripts_scripts(){
4511
 
4512
  if ( isset( $_GET['page'] ) ) {
4513
  if ( $_GET['page'] == 'wplivechat-menu-settings' ) {
4514
- wp_enqueue_script( "wplc-custom-script-tab-ace", WPLC_PLUGIN_URL.'/js/vendor/ace/ace.js', array('jquery'),WPLC_PLUGIN_VERSION );
4515
  } else if ( $_GET['page'] === 'wplivechat-menu-dashboard' || $_GET['page'] === 'wplivechat-menu' ) {
4516
  wplc_register_common_node();
4517
- wp_enqueue_script( 'wplc-custom-script-dashboard', WPLC_PLUGIN_URL.'/js/wplc_dashboard.js', array('jquery'), WPLC_PLUGIN_VERSION, true );
4518
  wp_localize_script('wplc-custom-script-dashboard', 'nifty_api_key', wplc_node_server_token_get());
4519
  }
4520
 
3
  Plugin Name: WP-Live Chat by 3CX
4
  Plugin URI: https://www.3cx.com/wp-live-chat/
5
  Description: The easiest to use website live chat plugin. Let your visitors chat with you and increase sales conversion rates with WP-Live Chat by 3CX.
6
+ Version: 8.1.3
7
  Author: 3CX
8
  Author URI: https://www.3cx.com/wp-live-chat/
9
  Domain Path: /languages
12
  */
13
 
14
  /*
15
+ = 8.1.3 - 2019-10-31
16
+ * Bugfix: Admin detected as an agent - doesn't show offline messages form
17
+ * Bugfix: Remove picture from chat box doesn't work properly
18
+ * Bugfix: Edge JS compatibility issue in dashboard has been fixed
19
+ * Bugfix: The page will no longer refresh upon ending a chat with an agent.
20
+ * New feature: Agent online/offline switch in Wordpress admin bar
21
+ * New feature: Adjustable chatbox height 30% - 80% of page size
22
+ * Improvement: Cleaned up async_storage functions
23
+ * Improvement: Better alignment for chat popup with no picture
24
+ * Improvement: Reworked agent online/offline functions
25
+ * Improvement: Default business hours are now 9:00 - 18:00 instead of 00:00 - 00:00
26
+ * Improvement: The 'Use Logged In User Details' feature has been moved to the 'Chat Box' settings page.
27
+
28
  = 8.1.2 - 2019-10-24
29
  * New feature: improved auto pop-up feature, now 3 options to choose from
30
  * New feature: Pop-up only when agents are online
390
  'wplc_avatar_source' => '',
391
  'wplc_bh_enable' => false,
392
  'wplc_bh_interval' => 0,
393
+ 'wplc_bh_hours_start' => 9,
394
  'wplc_bh_minutes_start' => 0,
395
+ 'wplc_bh_hours_end' => 18,
396
  'wplc_bh_minutes_end' => 0,
397
  'wplc_chat_delay' => 2,
398
  'wplc_chat_icon' => plugins_url( '/', __FILE__ ).'images/chaticon.png',
399
  'wplc_chat_logo' => '',
400
  'wplc_chat_name' => __( 'Admin', 'wp-live-chat-support'),
401
  'wplc_chat_pic' => plugins_url( '/', __FILE__ ).'images/picture-for-chat-box.jpg',
402
+ 'wplc_chatbox_height' => 70,
403
  'wplc_close_btn_text' => __("close", 'wp-live-chat-support'),
404
  'wplc_default_department' => -1,
405
  'wplc_delay_between_loops' => 500,
625
  add_action('activated_plugin', 'wplc_redirect_on_activate');
626
  add_action('wp_ajax_wplc_choose_accepting','wplc_action_callback');
627
  add_action('wp_ajax_wplc_choose_not_accepting','wplc_action_callback');
628
+ add_action('wp_ajax_wplc_agent_list','wplc_action_callback');
629
  add_action('wplc_hook_action_callback','wplc_choose_hook_control_action_callback');
630
  add_action('wplc_hook_admin_menu_layout_display_top','wplc_ma_hook_control_admin_meny_layout_display_top');
631
  add_action('edit_user_profile_update', 'wplc_maa_set_user_as_agent');
701
  $admins->remove_cap('wplc_ma_agent');
702
  }
703
 
704
+ $users = wplc_get_agent_users();
705
+ foreach($users as $user) {
706
+ delete_user_meta( $user->ID, 'wplc_user_department' );
707
+ delete_user_meta( $user->ID, 'wplc_ma_agent' );
708
+ delete_user_meta( $user->ID, 'wplc_user_bio' );
709
+ delete_user_meta( $user->ID, 'wplc_user_facebook' );
710
+ delete_user_meta( $user->ID, 'wplc_user_linkedin' );
711
+ delete_user_meta( $user->ID, 'wplc_user_tagline' );
712
+ delete_user_meta( $user->ID, 'wplc_user_twitter' );
713
+ }
 
 
 
714
  }
715
  }
716
 
801
 
802
  $uid = get_current_user_id();
803
  update_user_meta($uid, 'wplc_ma_agent', 1);
804
+ wplc_update_agent_time($uid);
805
 
806
  /* add caps to admin */
807
  if (current_user_can('manage_options')) {
928
  ));
929
  } else if ($_POST['action'] == "wplc_admin_set_transient") {
930
  do_action("wplc_hook_set_transient");
931
+ echo wplc_return_online_agents_array();
932
  } else if ($_POST['action'] == "wplc_admin_remove_transient") {
933
  do_action("wplc_hook_remove_transient");
934
+ echo wplc_return_online_agents_array();
935
  } else if ($_POST['action'] == 'wplc_hide_ftt') {
936
  update_option("WPLC_FIRST_TIME_TUTORIAL",true);
937
  }
1004
  }
1005
 
1006
  function wplc_admin_menu() {
1007
+ $cap = apply_filters("wplc_ma_filter_menu_control",array());
1008
+ /* If user is either an agent or an admin, access the page. */
1009
+ if(wplc_user_is_agent() || current_user_can("wplc_ma_agent")) {
1010
+ add_menu_page('WP Live Chat', __('Live Chat', 'wp-live-chat-support'), $cap[0], 'wplivechat-menu', 'wplc_admin_menu_layout', 'dashicons-format-chat');
1011
+ add_submenu_page('wplivechat-menu', __('Dashboard', 'wp-live-chat-support'), __('Dashboard', 'wp-live-chat-support'), $cap[1], 'wplivechat-menu-dashboard', 'wplc_admin_dashboard_layout');
1012
+ add_submenu_page('wplivechat-menu', __('Settings', 'wp-live-chat-support'), __('Settings', 'wp-live-chat-support'), $cap[1], 'wplivechat-menu-settings', 'wplc_admin_settings_layout');
1013
+ }
1014
 
1015
+ /* only if user is both an agent and an admin that has the cap assigned, can they access these pages */
1016
+ if(wplc_user_is_agent() && current_user_can("wplc_ma_agent")) {
1017
+ add_submenu_page('wplivechat-menu', __('History', 'wp-live-chat-support'), __('History', 'wp-live-chat-support'), $cap[2], 'wplivechat-menu-history', 'wplc_admin_history_layout');
1018
+ add_submenu_page('wplivechat-menu', __('Missed Chats', 'wp-live-chat-support'), __('Missed Chats', 'wp-live-chat-support'), $cap[3], 'wplivechat-menu-missed-chats', 'wplc_admin_missed_chats');
1019
+ add_submenu_page('wplivechat-menu', __('Offline Messages', 'wp-live-chat-support'), __('Offline Messages', 'wp-live-chat-support'), $cap[4], 'wplivechat-menu-offline-messages', 'wplc_admin_offline_messages');
1020
+ do_action("wplc_hook_menu_mid",$cap);
1021
+ add_submenu_page('wplivechat-menu', __('Support', 'wp-live-chat-support'), __('Support', 'wp-live-chat-support'), 'manage_options', 'wplivechat-menu-support-page', 'wplc_support_menu');
1022
+ }
1023
+ do_action("wplc_hook_menu");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1024
  }
1025
 
1026
 
1111
 
1112
  if ($wplc_settings['wplc_use_node_server']) {
1113
  wp_localize_script('wplc-server-script', 'tcx_api_key', wplc_node_server_token_get());
1114
+ wp_register_script('wplc-node-server-script', WPLC_PLUGIN_URL."js/vendor/sockets.io/socket.io.slim.js", array('jquery'), WPLC_PLUGIN_VERSION);
1115
  wp_enqueue_script('wplc-node-server-script');
1116
  wp_register_script('wplc-user-events-script', plugins_url('/js/wplc_u_node_events.js', __FILE__),array('jquery', 'wplc-server-script'),WPLC_PLUGIN_VERSION);
1117
  /* Not used in front-end
1123
 
1124
  //Emoji Libs
1125
  if (!$wplc_settings['wplc_disable_emojis']) {
1126
+ wp_register_script('wplc-user-js-emoji-concat', WPLC_PLUGIN_URL."js/vendor/wdt-emoji/wdt-emoji-concat.min.js", array("wplc-server-script", "wplc-server-script"), WPLC_PLUGIN_VERSION, false);
1127
  wp_enqueue_script('wplc-user-js-emoji-concat');
1128
+ wp_register_style( 'wplc-admin-style-emoji', WPLC_PLUGIN_URL."js/vendor/wdt-emoji/wdt-emoji-bundle.css", false, WPLC_PLUGIN_VERSION );
1129
  wp_enqueue_style( 'wplc-admin-style-emoji' );
1130
  }
1131
  wp_register_script('wplc-user-node-node-primary', plugins_url('/js/wplc_node.js', __FILE__),array('jquery', 'wplc-server-script', 'wplc-user-script'), WPLC_PLUGIN_VERSION);
1204
  /**
1205
  * Create a JS object for all Agent ID's and Gravatar MD5's
1206
  */
1207
+ $user_array = wplc_get_agent_users();
 
 
 
1208
  $a_array = array();
1209
+ foreach ($user_array as $user) {
1210
+ $a_array[$user->ID] = array();
1211
+ $a_array[$user->ID]['name'] = apply_filters( "wplc_decide_agents_name", sanitize_text_field($user->display_name), $wplc_settings );
1212
+ $a_array[$user->ID]['md5'] = md5( $user->user_email );
1213
+ $a_array[$user->ID]['tagline'] = get_user_meta($user->ID, 'wplc_user_tagline', true);
 
 
1214
  }
1215
  wp_localize_script('wplc-user-script', 'wplc_agent_data', $a_array);
1216
 
1518
 
1519
  default:
1520
  $wplc_theme_type = "modern";
1521
+ $hovercard_content = "";
1522
+ $msg_left = apply_filters("wplc_filter_modern_theme_hovercard_content_left","");
1523
+ if (!empty($msg_left)) {
1524
+ $hovercard_content.= "<div class='wplc_hovercard_content_left'>".$msg_left."</div>";
1525
+ }
1526
+ $hovercard_content.= "<div class='wplc_hovercard_content_right'>".apply_filters("wplc_filter_live_chat_box_html_1st_layer",wplc_filter_control_live_chat_box_html_1st_layer($wplc_settings,$logged_in,$wplc_using_locale,'wplc-color-4'))."</div>";
1527
  $hovercard_content = apply_filters("wplc_filter_hovercard_content", $hovercard_content);
1528
  $ret_msg .= "<div id='wplc_hovercard' style='display:none' class='".$wplc_theme_type."'>";
1529
  $ret_msg .= "<div id='wplc_hovercard_content'>".apply_filters("wplc_filter_live_chat_box_pre_layer1","").$hovercard_content."</div>";
1549
 
1550
  add_filter("wplc_filter_modern_theme_hovercard_content_left","wplc_filter_control_modern_theme_hovercard_content_left",10,1);
1551
  function wplc_filter_control_modern_theme_hovercard_content_left($msg) {
 
 
1552
  $msg = apply_filters("wplc_filter_microicon",$msg);
1553
  return $msg;
1554
  }
1793
  }
1794
 
1795
  /* admin not logged in, show offline messages */
 
 
 
1796
  $ret_msg = "<div id=\"wp-live-chat-2-info\" class=\"wplc-color-bg-1 wplc-color-2\">";
 
1797
  $ret_msg .= "</div>";
1798
  $ret_msg .= "<div id=\"wplc_message_div\">";
1799
  $ret_msg .= "<input type=\"text\" name=\"wplc_name\" id=\"wplc_name\" value=\"$wplc_loggedin_user_name\" placeholder=\"".__("Name", 'wp-live-chat-support')."\" />";
1946
  * @return string
1947
  * @since 6.0.00
1948
  */
1949
+ function wplc_filter_control_live_chat_box_html_1st_layer($wplc_settings, $logged_in, $wplc_using_locale, $class_override = false) {
1950
  global $wplc_default_settings_array;
1951
  $ret_msg = "<div id='wplc_first_message'>";
1952
  if ($logged_in) {
 
 
1953
  if ($wplc_settings['wplc_newtheme'] == "theme-2") {
1954
  $coltheme = "wplc-color-4";
1955
  } else {
1956
  $coltheme = "wplc-color-2";
1957
  }
1958
+ if ($class_override) {
 
1959
  //Override color class
1960
  $coltheme = $class_override;
1961
  }
1962
+ $wplc_tl_msg = "<div class='$coltheme'><strong>" . ($wplc_using_locale ? $wplc_default_settings_array['wplc_pro_fst1']: stripslashes($wplc_settings['wplc_pro_fst1'])) . "</strong> " . ( $wplc_using_locale ? $wplc_default_settings_array['wplc_pro_fst2'] : stripslashes($wplc_settings['wplc_pro_fst2'])) ."</div>";
1963
  $ret_msg .= $wplc_tl_msg;
1964
  } else {
1965
+ $wplc_tl_msg = "<div class='wplc_offline'><strong>" . ($wplc_using_locale ? $wplc_default_settings_array['wplc_pro_na'] : stripslashes($wplc_settings['wplc_pro_na'])) . "</strong> " . ( $wplc_using_locale ? $wplc_default_settings_array['wplc_pro_offline1'] : stripslashes($wplc_settings['wplc_pro_offline1'])) ."</div>";
 
1966
  $ret_msg .= $wplc_tl_msg;
1967
  }
1968
  $ret_msg .= "</div>";
1972
  add_filter("wplc_loggedin_filter","wplc_filter_control_loggedin",10,1);
1973
  function wplc_filter_control_loggedin($logged_in) {
1974
  $wplc_is_admin_logged_in = get_transient("wplc_is_admin_logged_in");
 
1975
  if ($wplc_is_admin_logged_in != 1) {
1976
  $logged_in = false;
1977
  } else {
1988
  if (isset($logged_in_checks['app']) && $logged_in_checks['app'] == true) { $logged_in_via_app = true; }
1989
 
1990
  $logged_in = apply_filters("wplc_final_loggedin_control",$logged_in,$logged_in_via_app);
 
1991
  /* admin is using the basic version and is logged in */
1992
  if ($wplc_is_admin_logged_in) { $logged_in = true; }
1993
 
2252
  */
2253
  function wplc_admin_output_js() {
2254
  $ajax_nonce = wp_create_nonce("wplc");
2255
+ if (wplc_user_is_agent()) {
 
2256
  $wplc_settings = wplc_get_options();
2257
  wp_register_script('wplc-admin-js', plugins_url('js/wplc_u_admin.js', __FILE__), false, WPLC_PLUGIN_VERSION, false);
2258
  wp_enqueue_script('wplc-admin-js');
2262
  wp_localize_script('wplc-admin-js', 'wplc_wav_file', $wplc_wav_file);
2263
  wp_localize_script('wplc-admin-js', 'wplc_ajax_nonce', $ajax_nonce);
2264
  wp_localize_script('wplc-admin-js', 'wplc_notification_icon', $not_icon);
2265
+ wp_localize_script('wplc-admin-js', 'tcx_favico_noti', WPLC_PLUGIN_URL . 'images/tcx48_n.png');
2266
  wp_localize_script('wplc-admin-js', 'tcx_favico', WPLC_PLUGIN_URL . 'images/tcx48px.png');
2267
  $extra_data = apply_filters("wplc_filter_admin_javascript",array());
2268
  wp_localize_script('wplc-admin-js', 'wplc_extra_data', $extra_data);
2331
  }
2332
 
2333
  function wplc_admin_menu_layout_display() {
2334
+ if (wplc_user_is_agent()) {
2335
+ do_action("wplc_hook_admin_menu_layout_display_top");
2336
+ wplc_stats("chat_dashboard");
2337
+ if (!isset($_GET['action'])) {
2338
+ ?>
2339
+ <div class='wplc_network_issue' style='display:none;'></div>
2340
+ <div class='wplc_page_title'>
2341
+ <?php wplc_first_time_tutorial(); ?>
2342
+ </div>
2343
+ <div id="wplc_sound"></div>
2344
+ <div id="wplc_admin_chat_holder">
2345
+ <div class="wplc_admin_chat_on_premise_header">
2346
+ <div class="wplc_admin_chat_on_premise_header_left">
2347
+ <img src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABkAAD/4QMvaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpERkVFRTcwRUFENDkxMUU5QjUzM0I0QThEMzhGNzc5MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpERkVFRTcwRkFENDkxMUU5QjUzM0I0QThEMzhGNzc5MyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkRGRUVFNzBDQUQ0OTExRTlCNTMzQjRBOEQzOEY3NzkzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkRGRUVFNzBEQUQ0OTExRTlCNTMzQjRBOEQzOEY3NzkzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4AJkFkb2JlAGTAAAAAAQMAFQQDBgoNAAAH7QAADocAABIG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" align="middle"> <h2>WP Live Chat by 3CX</h2>
2348
+ <?php do_action("wplc_hook_chat_dashboard_above"); ?>
2349
+ </div>
2350
+ <div id="wplc_admin_chat_info_new" class="wplc_admin_chat_on_premise_header_right">
2351
+ <div class="wplc_admin_chat_on_premise_switchery_label">
2352
+ <b><?php _e("Keep this window open to get notified of new chats.",'wp-live-chat-support'); ?></b>
2353
+ </div>
2354
+ <div class='wplc_chat_vis_count_box'>
2355
+ <?php do_action("wplc_hook_chat_dahsboard_visitors_online_top"); ?>
2356
+ <div class="wplc_chat_dashboard_on_premise_stats">
2357
+ <span class='wplc_vis_online'>0</span> <?php _e("Visitor(s) online",'wp-live-chat-support'); ?>
2358
+ </div>
2359
+ <div class="wplc_chat_dashboard_on_premise_stats">
2360
+ <?php echo apply_filters("wplc_filter_chat_dahsboard_visitors_online_bottom",""); ?>
2361
+ </div>
2362
+ <?php do_action("wplc_after_chat_visitor_count_hook"); ?>
2363
+ </div>
2364
+ </div>
2365
+ </div>
2366
+ <div id="wplc_admin_chat_area_new">
2367
+ <div style="display:block;">
2368
+ <div class='wplc_chat_on_premise_header'>
2369
+ <div class='wplc_header_vh wplc_header_v'><?php _e("Visitor",'wp-live-chat-support'); ?></div>
2370
+ <div class='wplc_header_vh wplc_header_t'><?php _e("Time",'wp-live-chat-support'); ?></div>
2371
+ <div class='wplc_header_vh wplc_header_nr'><?php _e("Type",'wp-live-chat-support'); ?></div>
2372
+ <div class='wplc_header_vh wplc_header_dev'><?php _e("Device",'wp-live-chat-support'); ?></div>
2373
+ <div class='wplc_header_vh wplc_header_d'><?php _e("Data",'wp-live-chat-support'); ?></div>
2374
+ <div class='wplc_header_vh wplc_header_s'><?php _e("Status",'wp-live-chat-support'); ?></div>
2375
+ <div class='wplc_header_vh wplc_header_a'><?php _e("Action",'wp-live-chat-support'); ?></div>
2376
+ </div>
2377
+ <div id='wplc_chat_ul'></div>
2378
+ </div>
2379
+ </div>
2380
+ </div>
2381
+ <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2382
  } else {
2383
+ if (isset($_GET['aid'])) { $aid = intval($_GET['aid']); } else { $aid = null; }
2384
+ if (!is_null($aid)) {
2385
+ do_action("wplc_hook_update_agent_id", intval($_GET['cid']), $aid);
2386
+ }
2387
+ if ($_GET['action'] == 'ac') {
2388
+ do_action('wplc_hook_accept_chat',$_GET, $aid);
2389
+ }
2390
+ do_action("wplc_hook_admin_menu_layout_display", $_GET['action'], intval($_GET['cid']), $aid);
 
 
 
 
2391
  }
2392
+ } else {
2393
+ ?>
2394
+ <h1><?php _e("Chat Dashboard",'wp-live-chat-support'); ?></h1>
2395
+ <div id="welcome-panel" class="welcome-panel">
2396
+ <div class="welcome-panel-content">
2397
+ <h2><?php _e("Oh no!",'wp-live-chat-support'); ?></h2>
2398
+ <p class="about-description">
2399
+ <?php echo sprintf(__("You do not have access to this page as %s.",'wp-live-chat-support'),'<strong>'.__('you are not a chat agent','wp-live-chat-support').'</strong>'); ?>
2400
+ </p>
2401
+ </div>
2402
+ </div>
2403
+ <?php
2404
+ }
2405
  }
2406
 
2407
  add_action("wplc_hook_change_status_on_answer","wplc_hook_control_change_status_on_answer",10,2);
2675
  /**
2676
  * Create a JS object for all Agent ID's and Gravatar MD5's
2677
  */
2678
+ $user_array = wplc_get_agent_users();
 
 
 
2679
  $a_array = array();
2680
+ foreach ($user_array as $user) {
2681
+ $a_array[$user->ID] = array();
2682
+ $a_array[$user->ID]['name'] = sanitize_text_field($user->display_name);
2683
+ $a_array[$user->ID]['md5'] = md5( $user->user_email );
 
 
2684
  }
2685
  wp_localize_script('wplc-admin-chat-server', 'wplc_agent_data', $a_array);
2686
 
2820
  $wplc_settings = wplc_cleanup_old_options($wplc_settings);
2821
  update_option('WPLC_SETTINGS', $wplc_settings);
2822
  $uid = get_current_user_id();
2823
+ wplc_set_agent_accepting($uid, true);
2824
  update_user_meta($uid, 'wplc_ma_agent', 1);
2825
+ wplc_update_agent_time($uid);
2826
 
2827
  $admins = get_role('administrator');
2828
  if( $admins !== null ) { $admins->add_cap('wplc_ma_agent'); }
2839
  if (!function_exists("wplc_choose_activate")) {
2840
  register_activation_hook(__FILE__, 'wplc_choose_activate');
2841
  function wplc_choose_activate( $networkwide ) {
2842
+ wplc_set_agent_accepting(get_current_user_id(),true);
2843
  wplc_mrg_update_db( $networkwide ); //Run update db
2844
  }
2845
  }
2852
  if (!function_exists("wplc_choose_deactivate")) {
2853
  register_deactivation_hook(__FILE__, 'wplc_choose_deactivate');
2854
  function wplc_choose_deactivate() {
2855
+ wplc_set_agent_accepting(get_current_user_id(),false);
2856
  }
2857
  }
2858
 
2963
  $close_icon = plugins_url('images/iconCloseRetina.png', __FILE__);
2964
 
2965
  $bg='';
2966
+ $bg_string = '';
2967
  if (!empty($wplc_settings['wplc_settings_bg'])) {
2968
  $bg = sanitize_text_field($wplc_settings['wplc_settings_bg']);
2969
  }
2973
  } else {
2974
  $bg_string = "#wp-live-chat-4 { background-color: #fff; }";
2975
  }
2976
+ if ($wplc_settings['wplc_chatbox_height']!=70) {
2977
+ $bg_string.= "#wp-live-chat-4 { height: ".$wplc_settings['wplc_chatbox_height']."% !important; }";
2978
+ }
2979
 
2980
  if (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ){ $icon = preg_replace('/^http:\/\//', 'https:\/\/', $icon); }
2981
  if (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ){ $close_icon = preg_replace('/^http:\/\//', 'https:\/\/', $close_icon); }
3056
  * @return void
3057
  */
3058
  function wplc_online_check_script() {
3059
+ if (wplc_user_is_agent()) {
3060
+ $ajax_nonce = wp_create_nonce("wplc");
3061
+ wp_register_script( 'wplc-heartbeat', plugins_url( 'js/wplc_heartbeat.js', __FILE__ ), array( 'jquery' ), WPLC_PLUGIN_VERSION, true );
3062
+ wp_enqueue_script( 'wplc-heartbeat' );
3063
+ wp_localize_script( 'wplc-heartbeat', 'wplc_transient_nonce', $ajax_nonce );
3064
+ $wplc_ajax_url = apply_filters("wplc_filter_ajax_url", admin_url('admin-ajax.php'));
3065
+ wp_localize_script('wplc-heartbeat', 'wplc_ajaxurl', $wplc_ajax_url);
3066
+ }
 
3067
  }
3068
 
3069
  /**
3073
  add_filter( 'heartbeat_received', 'wplc_heartbeat_receive', 10, 2 );
3074
  add_filter( 'heartbeat_nopriv_received', 'wplc_heartbeat_receive', 10, 2 );
3075
  function wplc_heartbeat_receive( $response, $data ) {
3076
+ if ( array_key_exists('client',$data) && $data['client'] == 'wplc_heartbeat' ) {
3077
+ if (wplc_user_is_agent()) {
3078
+ wplc_update_agent_time();
3079
+ wplc_hook_control_set_transient();
3080
+ }
3081
+ }
3082
+ return $response;
3083
  }
3084
 
3085
  /**
3565
  $do_popup=false;
3566
  if ($wplc_settings['wplc_auto_pop_up']>0) {
3567
  if ($wplc_settings['wplc_auto_pop_up_online']) {
3568
+ $do_popup=wplc_one_agent_is_online();
3569
  } else {
3570
  $do_popup=true;
3571
  }
3680
  $wplc_data['wplc_redirect_to_thank_you_page'] = stripslashes(sanitize_text_field(wplc_force_string($_POST, 'wplc_redirect_to_thank_you_page', $wplc_settings)));
3681
  $wplc_data['wplc_redirect_thank_you_url'] = esc_url(wplc_force_url($_POST, 'wplc_redirect_thank_you_url', $wplc_settings));
3682
  $wplc_data['wplc_disable_emojis'] = wplc_force_bool($_POST, 'wplc_disable_emojis');
3683
+ $wplc_data['wplc_chatbox_height'] = wplc_force_int($_POST, 'wplc_chatbox_height');
3684
+ if ($wplc_data['wplc_chatbox_height']<30) {
3685
+ $wplc_data['wplc_chatbox_height']=30;
3686
+ }
3687
+ if ($wplc_data['wplc_chatbox_height']>80) {
3688
+ $wplc_data['wplc_chatbox_height']=80;
3689
+ }
3690
  $wplc_data['wplc_record_ip_address'] = "0";
3691
  $wplc_data['wplc_enable_msg_sound'] = wplc_force_bool($_POST, 'wplc_enable_msg_sound');
3692
  $wplc_data['wplc_enable_visitor_sound'] = wplc_force_bool($_POST, 'wplc_enable_visitor_sound');
3773
  $wplc_upload_icon = wplc_force_string($_POST, 'wplc_upload_icon', '');
3774
 
3775
  if (!empty($wplc_upload_pic)) {
3776
+ if ($wplc_upload_pic=='remove') {
3777
+ $wplc_data['wplc_chat_pic'] = ''; //$wplc_default_settings_array['wplc_chat_pic']; // cannot be empty, set to default
3778
+ } else {
3779
+ $wplc_data['wplc_chat_pic'] = esc_url(base64_decode($wplc_upload_pic));
3780
+ }
3781
  }
3782
  if (!empty($wplc_upload_logo)) {
3783
+ if ($wplc_upload_logo=='remove') {
3784
+ $wplc_data['wplc_chat_logo'] = '';
3785
+ } else {
3786
+ $wplc_data['wplc_chat_logo'] = esc_url(base64_decode($wplc_upload_logo));
3787
+ }
3788
  }
3789
  if (!empty($wplc_upload_icon)) {
3790
+ if ($wplc_upload_icon=='remove') {
3791
+ $wplc_data['wplc_chat_icon'] = '';
3792
+ } else {
3793
+ $wplc_data['wplc_chat_icon'] = esc_url(base64_decode($wplc_upload_icon));
3794
+ }
3795
+
3796
  }
3797
 
3798
  $wplc_data['wplc_chat_delay'] = wplc_force_int($_POST, 'wplc_chat_delay');
3837
  if ($wplc_data['wplc_delay_between_loops'] > 1000000) { $wplc_data['wplc_delay_between_loops'] = 1000000; }
3838
 
3839
  if (isset($_POST['wplc_agent_select']) && $_POST['wplc_agent_select'] != "") {
3840
+ $user_array = wplc_get_agent_users();
3841
+ foreach ($user_array as $user) {
3842
+ $uid = $user->ID;
3843
+ $wplc_ma_user = new WP_User( $uid );
3844
+ $wplc_ma_user->remove_cap( 'wplc_ma_agent' );
3845
+ delete_user_meta($uid, "wplc_ma_agent");
3846
+ delete_user_meta($uid, "wplc_chat_agent_online");
 
 
 
 
3847
  }
3848
 
3849
  $uid = intval($_POST['wplc_agent_select']);
3850
  $wplc_ma_user = new WP_User( $uid );
3851
  $wplc_ma_user->add_cap( 'wplc_ma_agent' );
3852
  update_user_meta($uid, "wplc_ma_agent", 1);
3853
+ wplc_update_agent_time($uid);
3854
  }
3855
 
3856
  if (isset($_POST['wplc_ban_users_ip'])) {
3892
  delete_transient('wplc_is_admin_logged_in');
3893
  }
3894
 
 
 
3895
  /**
3896
  * Error checks used to ensure the user's resources meet the plugin's requirements
3897
  */
4175
  * @return file
4176
  */
4177
  function wplc_admin_download_chat_history(){
4178
+ if (!is_user_logged_in() || !wplc_user_is_agent()) {
4179
+ return;
4180
  }
4181
 
4182
  if (isset($_GET['action']) && $_GET['action'] == "download_history") {
4253
  * @return void
4254
  */
4255
  function wplc_admin_download_history($type, $cid){
4256
+ if (!is_user_logged_in() || !wplc_user_is_agent(get_current_user_id())) {
4257
+ return;
4258
  }
4259
 
4260
  global $wpdb;
4484
 
4485
  if ( isset( $_GET['page'] ) ) {
4486
  if ( $_GET['page'] == 'wplivechat-menu-settings' ) {
4487
+ wp_enqueue_script( "wplc-custom-script-tab-ace", WPLC_PLUGIN_URL.'js/vendor/ace/ace.js', array('jquery'),WPLC_PLUGIN_VERSION );
4488
  } else if ( $_GET['page'] === 'wplivechat-menu-dashboard' || $_GET['page'] === 'wplivechat-menu' ) {
4489
  wplc_register_common_node();
4490
+ wp_enqueue_script( 'wplc-custom-script-dashboard', WPLC_PLUGIN_URL.'js/wplc_dashboard.js', array('jquery'), WPLC_PLUGIN_VERSION, true );
4491
  wp_localize_script('wplc-custom-script-dashboard', 'nifty_api_key', wplc_node_server_token_get());
4492
  }
4493