From a66845036b924a8f236abd0e967a8db6c026c702 Mon Sep 17 00:00:00 2001
From: Makarand Bauskar
Date: Thu, 27 Jul 2017 09:01:48 +0530
Subject: [PATCH 01/52] [minor] revert enable all roles (#3790)
---
frappe/utils/install.py | 25 +------------------------
1 file changed, 1 insertion(+), 24 deletions(-)
diff --git a/frappe/utils/install.py b/frappe/utils/install.py
index ad08a0f2a5..a483487fc5 100644
--- a/frappe/utils/install.py
+++ b/frappe/utils/install.py
@@ -110,7 +110,6 @@ def before_tests():
"timezone" :"America/New_York",
"currency" :"USD"
})
- enable_all_roles_and_domains()
frappe.db.commit()
frappe.clear_cache()
@@ -153,26 +152,4 @@ def add_country_and_currency(name, country):
"smallest_currency_fraction_value": country.smallest_currency_fraction_value,
"number_format": country.number_format,
"docstatus": 0
- }).db_insert()
-
-def enable_all_roles_and_domains():
- """ enable all roles and domain for testing """
- roles = frappe.get_list("Role", filters={"disabled": 1})
- for role in roles:
- _role = frappe.get_doc("Role", role.get("name"))
- _role.disabled = 0
- _role.flags.ignore_mandatory = True
- _role.flags.ignore_permissions = True
- _role.save()
-
- domains = frappe.get_list("Domain")
- if not domains:
- return
-
- domain_settigns = frappe.get_doc("Domain Settings", "Domain Settings")
- domain_settigns.set("active_domains", [])
- for domain in domains:
- row = domain_settigns.append("active_domains", {})
- row.domain=domain.get("name")
-
- domain_settigns.save()
\ No newline at end of file
+ }).db_insert()
\ No newline at end of file
From bc8044c4e085b6fc3a8b65db2cd4266fcb621252 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Thu, 20 Jul 2017 17:48:24 +0530
Subject: [PATCH 02/52] [fix] no breadcrumbs in update-password
---
frappe/public/less/website.less | 2 +-
frappe/www/update_password.py | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/frappe/public/less/website.less b/frappe/public/less/website.less
index 55b70f2d86..a9d80cc494 100644
--- a/frappe/public/less/website.less
+++ b/frappe/public/less/website.less
@@ -689,7 +689,7 @@ li.footer-child-item {
margin: 70px auto;
border: 1px solid @border-color;
border-radius: 4px;
- background-color: #fff;
+ background-color: #fff;
box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
.page-card-head {
diff --git a/frappe/www/update_password.py b/frappe/www/update_password.py
index 5ed7ad913d..7dc23cd494 100644
--- a/frappe/www/update_password.py
+++ b/frappe/www/update_password.py
@@ -8,4 +8,5 @@ no_sitemap = 1
no_cache = 1
def get_context(context):
+ context.no_breadcrumbs = True
context.parents = [{"name":"me", "title":_("My Account")}]
From 25dcdd24623e350a14e2eb2a96085859c4d4aea0 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Mon, 24 Jul 2017 11:52:18 +0530
Subject: [PATCH 03/52] [minor] add clear in msgpring
---
frappe/public/js/frappe/ui/messages.js | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js
index 761f87a202..35f3e93f8a 100644
--- a/frappe/public/js/frappe/ui/messages.js
+++ b/frappe/public/js/frappe/ui/messages.js
@@ -137,11 +137,16 @@ frappe.msgprint = function(msg, title) {
data.message = '';
}
- if(data.message.search(/ ||
/)==-1)
+ if(data.message.search(/ ||
/)==-1) {
msg = replace_newlines(data.message);
+ }
-
- var msg_exists = msg_dialog.msg_area.html();
+ if(data.clear) {
+ msg_dialog.msg_area.empty();
+ var msg_exists = false;
+ } else {
+ var msg_exists = msg_dialog.msg_area.html();
+ }
if(data.title || !msg_exists) {
// set title only if it is explicitly given
From 377f233ca46da8f1172f4ca2f46e22c846a1e53a Mon Sep 17 00:00:00 2001
From: bcornwellmott
Date: Wed, 26 Jul 2017 22:54:50 -0700
Subject: [PATCH 04/52] Allow workflow state and status in listview (#3757)
* Allow workflow state and status in listview
* Clear trailing blankspace
* Fixed bug when missing override_status
* Commonized duplicate code
---
frappe/public/js/frappe/list/list_renderer.js | 10 ++++++----
frappe/public/js/frappe/model/indicator.js | 4 ++--
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/frappe/public/js/frappe/list/list_renderer.js b/frappe/public/js/frappe/list/list_renderer.js
index 02940e1bec..1a6b6aa07c 100644
--- a/frappe/public/js/frappe/list/list_renderer.js
+++ b/frappe/public/js/frappe/list/list_renderer.js
@@ -405,7 +405,7 @@ frappe.views.ListRenderer = Class.extend({
},
get_indicator_html: function (doc) {
- var indicator = frappe.get_indicator(doc, this.doctype);
+ var indicator = this.get_indicator_from_doc(doc);
if (indicator) {
return `
@@ -414,15 +414,17 @@ frappe.views.ListRenderer = Class.extend({
}
return '';
},
-
get_indicator_dot: function (doc) {
- var indicator = frappe.get_indicator(doc, this.doctype);
+ var indicator = this.get_indicator_from_doc(doc);
if (!indicator) {
return '';
}
return ` `;
},
-
+ get_indicator_from_doc: function (doc) {
+ var workflow = frappe.workflow.workflows[this.doctype];
+ return frappe.get_indicator(doc, this.doctype, (workflow && workflow['override_status']) || true);
+ },
prepare_data: function (data) {
if (data.modified)
this.prepare_when(data, data.modified);
diff --git a/frappe/public/js/frappe/model/indicator.js b/frappe/public/js/frappe/model/indicator.js
index d033b3e8c9..d4c0807d7c 100644
--- a/frappe/public/js/frappe/model/indicator.js
+++ b/frappe/public/js/frappe/model/indicator.js
@@ -14,7 +14,7 @@ frappe.has_indicator = function(doctype) {
return false;
}
-frappe.get_indicator = function(doc, doctype) {
+frappe.get_indicator = function(doc, doctype, without_workflow = true) {
if(doc.__unsaved) {
return [__("Not Saved"), "orange"];
}
@@ -27,7 +27,7 @@ frappe.get_indicator = function(doc, doctype) {
workflow_fieldname = frappe.workflow.get_state_fieldname(doctype);
// workflow
- if(workflow_fieldname) {
+ if(workflow_fieldname && !without_workflow) {
var value = doc[workflow_fieldname];
if(value) {
var colour = "";
From d56fbaba41c6e244fe4a1de6fb8a93c16bef06c9 Mon Sep 17 00:00:00 2001
From: omkarghaisas
Date: Thu, 27 Jul 2017 11:32:40 +0530
Subject: [PATCH 05/52] Third party apps portal (#3782)
* Added third party apps portal page stub
* [WIP] third party apps portal page
* Added portal page third party apps
Added page to manage OAuth 2.0 active sessions
* [Fix] Typo me.html
* frappe/www/third_party_apps.
* [Fix] Added column for last log in
---
.../includes/integrations/third_party_apps.js | 9 +++
frappe/www/me.html | 6 +-
frappe/www/third_party_apps.html | 66 +++++++++++++++++++
frappe/www/third_party_apps.py | 53 +++++++++++++++
4 files changed, 132 insertions(+), 2 deletions(-)
create mode 100644 frappe/templates/includes/integrations/third_party_apps.js
create mode 100644 frappe/www/third_party_apps.html
create mode 100644 frappe/www/third_party_apps.py
diff --git a/frappe/templates/includes/integrations/third_party_apps.js b/frappe/templates/includes/integrations/third_party_apps.js
new file mode 100644
index 0000000000..fe75f23db9
--- /dev/null
+++ b/frappe/templates/includes/integrations/third_party_apps.js
@@ -0,0 +1,9 @@
+frappe.ready(() => {
+ $(".btn-delete-app").on("click", function(event) {
+ frappe.call({
+ method:"frappe.www.third_party_apps.delete_client",
+ args: {"client_id": $(this).data("client_id"),
+ }
+ }).done(r => location.href="/third_party_apps");
+ });
+});
diff --git a/frappe/www/me.html b/frappe/www/me.html
index 1397eb9437..593fefc012 100644
--- a/frappe/www/me.html
+++ b/frappe/www/me.html
@@ -18,10 +18,12 @@
{{ _("Reset Password") }}
-
+
{{ _("Edit Profile") }}
-
+
+ {{ _("Manage Third Party Apps") }}
+
diff --git a/frappe/www/third_party_apps.html b/frappe/www/third_party_apps.html
new file mode 100644
index 0000000000..baf62fa641
--- /dev/null
+++ b/frappe/www/third_party_apps.html
@@ -0,0 +1,66 @@
+{% extends "templates/web.html" %}
+
+{% block title %} {{ _("Third Party Apps") }} {% endblock %}
+{% block header %}
+ {{ _("Third Party Apps") }}
+{% endblock %}
+
+{% block page_sidebar %}
+{% include "templates/pages/web_sidebar.html" %}
+{% endblock %}
+
+{% block style %}
+{% endblock %}
+
+{% block page_content %}
+
+
+
+
+
+{% if app %}
+{{ app.app_name }}
+
+
+
+
+
{{ _("This will log out {0} from all other devices".format(app.app_name)) }}
+
+
+ Cancel
+ Revoke
+
+
+
+
+
+{% elif apps|length > 0 %}
+{{ _("Active Sessions") }}
+ {% for app in apps %}
+
+
+
+ {{ app.app_name }}
+
+
+
+ {{ _("logged in") }} {{ frappe.utils.pretty_date(app.creation) }}
+
+
+
+
+
+ {% endfor %}
+{% else %}
+
+ {{ _("No Active Sessions")}}
+
+{% endif %}
+
+
+
+{% endblock %}
diff --git a/frappe/www/third_party_apps.py b/frappe/www/third_party_apps.py
new file mode 100644
index 0000000000..b70f795948
--- /dev/null
+++ b/frappe/www/third_party_apps.py
@@ -0,0 +1,53 @@
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+import frappe.www.list
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ if frappe.session.user == 'Guest':
+ frappe.throw(_("You need to be logged in to access this page"), frappe.PermissionError)
+
+ active_tokens = frappe.get_all("OAuth Bearer Token",
+ filters=[["user", "=", frappe.session.user]],
+ fields=["client"], distinct=True, order_by="creation")
+
+ client_apps = []
+
+ for token in active_tokens:
+ creation = get_first_login(token.client)
+ app = {
+ "name": token.get("client"),
+ "app_name": frappe.db.get_value("OAuth Client", token.get("client"), "app_name"),
+ "creation": creation
+ }
+ client_apps.append(app)
+
+ app = None
+ if (frappe.form_dict.has_key("app")):
+ app = frappe.get_doc("OAuth Client", frappe.form_dict.app)
+ app = app.__dict__
+ app["client_secret"] = None
+
+ if app:
+ context.app = app
+
+ context.apps = client_apps
+ context.show_sidebar = True
+
+def get_first_login(client):
+ login_date = frappe.get_all("OAuth Bearer Token",
+ filters=[["user", "=", frappe.session.user], ["client", "=", client]],
+ fields=["creation"], order_by="creation", limit=1)
+
+ login_date = login_date[0].get("creation") if login_date and len(login_date) > 0 else None
+
+ return login_date
+
+@frappe.whitelist()
+def delete_client(client_id):
+ active_client_id_tokens = frappe.get_all("OAuth Bearer Token", filters=[["user", "=", frappe.session.user], ["client","=", client_id]])
+ for token in active_client_id_tokens:
+ frappe.delete_doc("OAuth Bearer Token", token.get("name"), ignore_permissions=True)
\ No newline at end of file
From 1332710982f9b7242025e9b8506ece004c4eb7dc Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Thu, 27 Jul 2017 11:33:31 +0530
Subject: [PATCH 06/52] Email footer (#3784)
* Add frappe.preview_email for faster feedback on email design
* Set Unsubscribe link color to text-muted
* error handling for header
* codacy fixes
---
frappe/email/email_body.py | 14 ++++++++++++--
frappe/email/queue.py | 2 +-
frappe/public/build.json | 1 +
frappe/public/js/frappe/misc/preview_email.js | 16 ++++++++++++++++
4 files changed, 30 insertions(+), 3 deletions(-)
create mode 100644 frappe/public/js/frappe/misc/preview_email.js
diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py
index 7f97a34b4d..80005eef1d 100755
--- a/frappe/email/email_body.py
+++ b/frappe/email/email_body.py
@@ -251,6 +251,16 @@ def get_formatted_html(subject, message, footer=None, print_html=None, email_acc
transformed_html = inline_style_in_html(sanitized_html)
return transformed_html
+@frappe.whitelist()
+def get_email_html(template, args, subject, header=None):
+ import json
+
+ args = json.loads(args)
+ if header and header.startswith('['):
+ header = json.loads(header)
+ email = frappe.utils.jinja.get_email_from_template(template, args)
+ return get_formatted_html(subject, email[0], header=header)
+
def inline_style_in_html(html):
''' Convert email.css and html to inline-styled html
'''
@@ -334,8 +344,6 @@ def get_footer(email_account, footer=None):
if email_account and email_account.footer:
footer += '{0}
'.format(email_account.footer)
- footer += ""
-
company_address = frappe.db.get_default("email_footer_address")
if company_address:
@@ -347,6 +355,8 @@ def get_footer(email_account, footer=None):
.format(x)
footer += ""
+ footer += ""
+
if not cint(frappe.db.get_default("disable_standard_email_footer")):
for default_mail_footer in frappe.get_hooks("default_mail_footer"):
footer += '{0}
'.format(default_mail_footer)
diff --git a/frappe/email/queue.py b/frappe/email/queue.py
index e5630bc88e..ed7337bd93 100755
--- a/frappe/email/queue.py
+++ b/frappe/email/queue.py
@@ -236,7 +236,7 @@ def get_unsubscribe_message(unsubscribe_message, expose_recipients):
html = """
- " style="color: #8d99a6; text-decoration: underline;"
target="_blank">{unsubscribe_message}
diff --git a/frappe/public/build.json b/frappe/public/build.json
index 3fafb6c5f2..433631c0a9 100755
--- a/frappe/public/build.json
+++ b/frappe/public/build.json
@@ -132,6 +132,7 @@
"public/js/frappe/misc/help.js",
"public/js/frappe/misc/help_links.js",
"public/js/frappe/misc/address_and_contact.js",
+ "public/js/frappe/misc/preview_email.js",
"public/js/frappe/ui/upload.html",
"public/js/frappe/upload.js",
diff --git a/frappe/public/js/frappe/misc/preview_email.js b/frappe/public/js/frappe/misc/preview_email.js
new file mode 100644
index 0000000000..b3e3bfddce
--- /dev/null
+++ b/frappe/public/js/frappe/misc/preview_email.js
@@ -0,0 +1,16 @@
+frappe.preview_email = function(template, args, header) {
+ frappe.call({
+ method: 'frappe.email.email_body.get_email_html',
+ args: {
+ subject: 'Test',
+ template,
+ args,
+ header
+ }
+ }).then((r) => {
+ var html = r.message;
+ html = html.replace(/embed=/, 'src=');
+ var d = frappe.msgprint(html);
+ d.$wrapper.find('.modal-dialog').css('width', '70%');
+ });
+};
From aef98daae42b1316ab7bc19efb1cc421ee25ef78 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Thu, 27 Jul 2017 11:34:44 +0530
Subject: [PATCH 07/52] [add] catch errors flake8 (#3800)
---
.travis.yml | 3 +++
.../{controller.py => controller._py} | 0
...test_controller.py => test_controller._py} | 0
frappe/core/doctype/doctype/doctype.py | 4 ++--
frappe/core/doctype/domain/domain.json | 4 ++--
frappe/core/doctype/domain/test_domain.js | 23 +++++++++++++++++++
frappe/core/doctype/has_role/has_role.py | 5 ++--
frappe/email/doctype/newsletter/newsletter.py | 3 +--
.../gsuite_settings/gsuite_settings.py | 2 +-
frappe/modules/utils.py | 2 ++
10 files changed, 36 insertions(+), 10 deletions(-)
rename frappe/core/doctype/doctype/boilerplate/{controller.py => controller._py} (100%)
rename frappe/core/doctype/doctype/boilerplate/{test_controller.py => test_controller._py} (100%)
create mode 100644 frappe/core/doctype/domain/test_domain.js
diff --git a/.travis.yml b/.travis.yml
index 1551f17ec5..2a60d20c6f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,6 +15,9 @@ services:
- mysql
install:
+ - pip install flake8 # pytest
+ # stop the build if there are Python syntax errors or undefined names
+ - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo apt-get purge -y mysql-common mysql-server mysql-client
- nvm install v7.10.0
diff --git a/frappe/core/doctype/doctype/boilerplate/controller.py b/frappe/core/doctype/doctype/boilerplate/controller._py
similarity index 100%
rename from frappe/core/doctype/doctype/boilerplate/controller.py
rename to frappe/core/doctype/doctype/boilerplate/controller._py
diff --git a/frappe/core/doctype/doctype/boilerplate/test_controller.py b/frappe/core/doctype/doctype/boilerplate/test_controller._py
similarity index 100%
rename from frappe/core/doctype/doctype/boilerplate/test_controller.py
rename to frappe/core/doctype/doctype/boilerplate/test_controller._py
diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py
index 2e13e64f57..40207a24dd 100644
--- a/frappe/core/doctype/doctype/doctype.py
+++ b/frappe/core/doctype/doctype/doctype.py
@@ -330,10 +330,10 @@ class DocType(Document):
def make_controller_template(self):
"""Make boilerplate controller template."""
- make_boilerplate("controller.py", self)
+ make_boilerplate("controller._py", self)
if not (self.istable or self.issingle):
- make_boilerplate("test_controller.py", self.as_dict())
+ make_boilerplate("test_controller._py", self.as_dict())
if not self.istable:
make_boilerplate("controller.js", self.as_dict())
diff --git a/frappe/core/doctype/domain/domain.json b/frappe/core/doctype/domain/domain.json
index 35b68d0714..f257d02ae8 100644
--- a/frappe/core/doctype/domain/domain.json
+++ b/frappe/core/doctype/domain/domain.json
@@ -26,7 +26,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"in_standard_filter": 0,
"label": "Domain",
"length": 0,
@@ -54,7 +54,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-06-16 13:03:25.430679",
+ "modified": "2017-07-26 21:29:00.353105",
"modified_by": "Administrator",
"module": "Core",
"name": "Domain",
diff --git a/frappe/core/doctype/domain/test_domain.js b/frappe/core/doctype/domain/test_domain.js
new file mode 100644
index 0000000000..6d8bd8039d
--- /dev/null
+++ b/frappe/core/doctype/domain/test_domain.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Domain", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially('Domain', [
+ // insert a new Domain
+ () => frappe.tests.make([
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/frappe/core/doctype/has_role/has_role.py b/frappe/core/doctype/has_role/has_role.py
index 44c27098d9..45e76c85a1 100644
--- a/frappe/core/doctype/has_role/has_role.py
+++ b/frappe/core/doctype/has_role/has_role.py
@@ -7,7 +7,6 @@ import frappe
from frappe.model.document import Document
class HasRole(Document):
- def validate(self):
- if cint(self.get("__islocal")) and frappe.db.exists("Has Role", {
- "parent": self.parent, "role": self.role}):
+ def before_insert(self):
+ if frappe.db.exists("Has Role", {"parent": self.parent, "role": self.role}):
frappe.throw(frappe._("User '{0}' already has the role '{1}'").format(self.parent, self.role))
diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py
index 29ecbee853..4f4713edbe 100755
--- a/frappe/email/doctype/newsletter/newsletter.py
+++ b/frappe/email/doctype/newsletter/newsletter.py
@@ -13,7 +13,6 @@ from frappe.utils.background_jobs import enqueue
from frappe.utils.scheduler import log
from frappe.email.queue import send
from frappe.email.doctype.email_group.email_group import add_subscribers
-from frappe.utils.file_manager import get_file
from frappe.utils import parse_addr
@@ -68,7 +67,7 @@ class Newsletter(Document):
files = frappe.get_all("File", fields = ["name"], filters = {"attached_to_doctype": "Newsletter",
"attached_to_name":self.name}, order_by="creation desc")
- for file in files:
+ for a in files:
try:
# these attachments will be attached on-demand
# and won't be stored in the message
diff --git a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py b/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py
index 9b6be3422d..29b1b64897 100644
--- a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py
+++ b/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py
@@ -17,7 +17,7 @@ class GSuiteSettings(Document):
def get_access_token(self):
if not self.refresh_token:
- raise UserError(_("Google GSuite is not configured."))
+ raise frappe.ValidationError(_("Google GSuite is not configured."))
data = {
'client_id': self.client_id,
'client_secret': self.get_password(fieldname='client_secret',raise_exception=False),
diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py
index 2acb5b5db6..20ff7bb28f 100644
--- a/frappe/modules/utils.py
+++ b/frappe/modules/utils.py
@@ -206,6 +206,8 @@ def get_app_publisher(module):
def make_boilerplate(template, doc, opts=None):
target_path = get_doc_path(doc.module, doc.doctype, doc.name)
template_name = template.replace("controller", scrub(doc.name))
+ if template_name.endswith('._py'):
+ template_name = template_name[:-4] + '.py'
target_file_path = os.path.join(target_path, template_name)
if not doc: doc = {}
From be60a22365893aad82d6dd474b448e6a2ce01120 Mon Sep 17 00:00:00 2001
From: Utkarsh Goswami
Date: Thu, 27 Jul 2017 17:44:54 +0530
Subject: [PATCH 08/52] [UI Test Report] Test for Query Report (#3801)
* Updated Test for Query Report
* Correct path updated
---
.../core/doctype/report/test_query_report.js | 33 +++++++++++++++++++
frappe/tests/ui/tests.txt | 3 +-
2 files changed, 35 insertions(+), 1 deletion(-)
create mode 100644 frappe/core/doctype/report/test_query_report.js
diff --git a/frappe/core/doctype/report/test_query_report.js b/frappe/core/doctype/report/test_query_report.js
new file mode 100644
index 0000000000..c51884cd21
--- /dev/null
+++ b/frappe/core/doctype/report/test_query_report.js
@@ -0,0 +1,33 @@
+// Test for creating query report
+QUnit.test("Test Query Report", function(assert){
+ assert.expect(2);
+ let done = assert.async();
+ let random = frappe.utils.get_random(10);
+ frappe.run_serially([
+ () => frappe.set_route('List', 'ToDo'),
+ () => frappe.new_doc('ToDo'),
+ () => frappe.quick_entry.dialog.set_value('description', random),
+ () => frappe.quick_entry.insert(),
+ () => {
+ return frappe.tests.make('Report', [
+ {report_name: 'ToDo List Report'},
+ {report_type: 'Query Report'},
+ {ref_doctype: 'ToDo'}
+ ]);
+ },
+ () => frappe.set_route('Form','Report', 'ToDo List Report'),
+
+ //Query
+ () => cur_frm.set_value('query','select description,owner,status from `tabToDo`'),
+ () => cur_frm.save(),
+ () => frappe.set_route('query-report','ToDo List Report'),
+ () => frappe.timeout(5),
+ () => {
+ assert.ok($('div.slick-header-column').length == 4,'Correct numbers of columns visible');
+ //To check if the result is present
+ assert.ok($('div.r1:contains('+random+')').is(':visible'),'Result is visible in report');
+ frappe.timeout(3);
+ },
+ () => done()
+ ]);
+});
diff --git a/frappe/tests/ui/tests.txt b/frappe/tests/ui/tests.txt
index ce0c91c77e..aeb562f76e 100644
--- a/frappe/tests/ui/tests.txt
+++ b/frappe/tests/ui/tests.txt
@@ -6,4 +6,5 @@ frappe/tests/ui/test_calendar_view.js
frappe/tests/ui/test_kanban/test_kanban_creation.js
frappe/tests/ui/test_kanban/test_kanban_view.js
frappe/tests/ui/test_kanban/test_kanban_filters.js
-frappe/tests/ui/test_kanban/test_kanban_column.js
\ No newline at end of file
+frappe/tests/ui/test_kanban/test_kanban_column.js
+frappe/core/doctype/report/test_query_report.js
\ No newline at end of file
From 3f93565553f0e64c243671d7a7698d363348be0f Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Thu, 27 Jul 2017 17:51:20 +0530
Subject: [PATCH 09/52] Email designs (#3786)
* New message email
* Mentioned in a comment
* File backup email
* Feedback email
* Administrator logged in email
* Upcoming events email
* minor
* Add header title and indicator color
---
frappe/core/doctype/communication/comment.py | 15 +++++-----
.../feedback_trigger/feedback_trigger.py | 10 +++++--
frappe/core/doctype/user/user.py | 30 ++++++++-----------
frappe/desk/doctype/event/event.py | 20 +++++++------
frappe/desk/page/backups/backups.py | 11 +++++--
frappe/desk/page/chat/chat.py | 9 ++++--
frappe/public/css/email.css | 3 ++
frappe/public/less/email.less | 4 +++
.../emails/administrator_logged_in.html | 3 ++
.../emails/feedback_request_url.html | 2 +-
frappe/templates/emails/new_message.html | 6 ++--
frappe/templates/emails/upcoming_events.html | 9 ++++++
frappe/utils/jinja.py | 4 +--
13 files changed, 78 insertions(+), 48 deletions(-)
create mode 100644 frappe/templates/emails/administrator_logged_in.html
create mode 100644 frappe/templates/emails/upcoming_events.html
diff --git a/frappe/core/doctype/communication/comment.py b/frappe/core/doctype/communication/comment.py
index 96c3e59d84..b5f0f141bc 100644
--- a/frappe/core/doctype/communication/comment.py
+++ b/frappe/core/doctype/communication/comment.py
@@ -82,12 +82,7 @@ def notify_mentions(doc):
sender_fullname = get_fullname(frappe.session.user)
parent_doc_label = "{0} {1}".format(_(doc.reference_doctype), doc.reference_name)
- subject = _("{0} mentioned you in a comment in {1}").format(sender_fullname, parent_doc_label)
- message = frappe.get_template("templates/emails/mentioned_in_comment.html").render({
- "sender_fullname": sender_fullname,
- "comment": doc,
- "link": get_link_to_form(doc.reference_doctype, doc.reference_name, label=parent_doc_label)
- })
+ subject = _("{0} mentioned you in a comment").format(sender_fullname)
recipients = [frappe.db.get_value("User", {"enabled": 1, "username": username, "user_type": "System User"})
for username in mentions]
@@ -96,7 +91,13 @@ def notify_mentions(doc):
recipients=recipients,
sender=frappe.session.user,
subject=subject,
- message=message
+ template="mentioned_in_comment",
+ args={
+ "sender_fullname": sender_fullname,
+ "comment": doc,
+ "link": get_link_to_form(doc.reference_doctype, doc.reference_name, label=parent_doc_label)
+ },
+ header=[_('New Mention'), 'orange']
)
def get_comments_from_parent(doc):
diff --git a/frappe/core/doctype/feedback_trigger/feedback_trigger.py b/frappe/core/doctype/feedback_trigger/feedback_trigger.py
index 6b9ca3e46a..e40f668d58 100644
--- a/frappe/core/doctype/feedback_trigger/feedback_trigger.py
+++ b/frappe/core/doctype/feedback_trigger/feedback_trigger.py
@@ -66,12 +66,16 @@ def send_feedback_request(reference_doctype, reference_name, trigger="Manual", d
feedback_request, url = get_feedback_request_url(reference_doctype,
reference_name, details.get("recipients"), trigger)
- feedback_url = frappe.render_template("templates/emails/feedback_request_url.html", { "url": url })
+ feedback_msg = frappe.render_template("templates/emails/feedback_request_url.html", { "url": url })
# appending feedback url to message body
- details.update({ "message": "{message}{feedback_url}".format(
+ message = "{message}{feedback_msg}".format(
message=details.get("message"),
- feedback_url=feedback_url)
+ feedback_msg=feedback_msg
+ )
+ details.update({
+ "message": message,
+ "header": [details.get('subject'), 'blue']
})
if details:
diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py
index da08997456..61324618eb 100644
--- a/frappe/core/doctype/user/user.py
+++ b/frappe/core/doctype/user/user.py
@@ -858,25 +858,21 @@ def notify_admin_access_to_system_manager(login_manager=None):
and login_manager.user == "Administrator"
and frappe.local.conf.notify_admin_access_to_system_manager):
- message = """
- {dear_system_manager}
- {access_message}
- {is_it_unauthorized}
-
""".format(
- dear_system_manager=_("Dear System Manager,"),
-
- access_message=_("""Administrator accessed {0} on {1} via IP Address {2}.""").format(
- """{site} """.format(site=frappe.local.request.host_url),
- """{date_and_time} """.format(date_and_time=format_datetime(now_datetime(), format_string="medium")),
- frappe.local.request_ip
- ),
-
- is_it_unauthorized=_("If you think this is unauthorized, please change the Administrator password.")
+ site = '{0} '.format(frappe.local.request.host_url)
+ date_and_time = '{0} '.format(format_datetime(now_datetime(), format_string="medium"))
+ ip_address = frappe.local.request_ip
+
+ access_message = _('Administrator accessed {0} on {1} via IP Address {2}.').format(
+ site, date_and_time, ip_address)
+
+ frappe.sendmail(
+ recipients=get_system_managers(),
+ subject=_("Administrator Logged In"),
+ template="administrator_logged_in",
+ args={'access_message': access_message},
+ header=[subject, 'orange']
)
- frappe.sendmail(recipients=get_system_managers(), subject=_("Administrator Logged In"),
- message=message)
-
def extract_mentions(txt):
"""Find all instances of @username in the string.
The mentions will be separated by non-word characters or may appear at the start of the string"""
diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py
index 66701c9c5a..b77b708ae6 100644
--- a/frappe/desk/doctype/event/event.py
+++ b/frappe/desk/doctype/event/event.py
@@ -7,7 +7,7 @@ import frappe
import json
from frappe.utils import (getdate, cint, add_months, date_diff, add_days,
- nowdate, get_datetime_str, cstr, get_datetime, now_datetime)
+ nowdate, get_datetime_str, cstr, get_datetime, now_datetime, format_datetime)
from frappe.model.document import Document
from frappe.utils.user import get_enabled_system_users
from frappe.desk.reportview import get_filters_cond
@@ -48,20 +48,22 @@ def send_event_digest():
for user in get_enabled_system_users():
events = get_events(today, today, user.name, for_reminder=True)
if events:
- text = ""
frappe.set_user_lang(user.name, user.language)
- text = "" + frappe._("Events In Today's Calendar") + " "
for e in events:
+ e.starts_on = format_datetime(e.starts_on, 'hh:mm a')
if e.all_day:
e.starts_on = "All Day"
- text += "%(starts_on)s: %(subject)s %(description)s
" % e
- text += ''\
- + frappe._("Daily Event Digest is sent for Calendar Events where reminders are set.")+'
'
-
- frappe.sendmail(recipients=user.email, subject=frappe._("Upcoming Events for Today"),
- content = text)
+ frappe.sendmail(
+ recipients=user.email,
+ subject=frappe._("Upcoming Events for Today"),
+ template="upcoming_events",
+ args={
+ 'events': events,
+ },
+ header=[frappe._("Events in Today's Calendar"), 'blue']
+ )
@frappe.whitelist()
def get_events(start, end, user=None, for_reminder=False, filters=None):
diff --git a/frappe/desk/page/backups/backups.py b/frappe/desk/page/backups/backups.py
index f3517c6953..2d493515b7 100644
--- a/frappe/desk/page/backups/backups.py
+++ b/frappe/desk/page/backups/backups.py
@@ -76,9 +76,14 @@ def backup_files_and_notify_user(user_email=None):
backup_files = backup(with_files=True)
get_downloadable_links(backup_files)
- subject = "File backup is ready"
- message = frappe.render_template('frappe/templates/emails/file_backup_notification.html', backup_files, is_path=True)
- frappe.sendmail(recipients=[user_email], subject=subject, message=message)
+ subject = _("File backup is ready")
+ frappe.sendmail(
+ recipients=[user_email],
+ subject=subject,
+ template="file_backup_notification",
+ args=backup_files,
+ header=[subject, 'green']
+ )
def get_downloadable_links(backup_files):
for key in ['backup_path_files', 'backup_path_private_files']:
diff --git a/frappe/desk/page/chat/chat.py b/frappe/desk/page/chat/chat.py
index a0ea8b7393..19f4d4cae4 100644
--- a/frappe/desk/page/chat/chat.py
+++ b/frappe/desk/page/chat/chat.py
@@ -6,6 +6,7 @@ import frappe
from frappe.desk.notifications import delete_notification_count_for
from frappe.core.doctype.user.user import STANDARD_USERS
from frappe.utils import cint
+from frappe import _
@frappe.whitelist()
def get_list(arg=None):
@@ -132,11 +133,13 @@ def _notify(contact, txt, subject=None):
frappe.sendmail(\
recipients=contact,
sender= frappe.db.get_value("User", frappe.session.user, "email"),
- subject=subject or "New Message from " + get_fullname(frappe.session.user),
- message=frappe.get_template("templates/emails/new_message.html").render({
+ subject=subject or _("New Message from {0}").format(get_fullname(frappe.session.user)),
+ template="new_message",
+ args={
"from": get_fullname(frappe.session.user),
"message": txt,
"link": get_url()
- }))
+ },
+ header=[_('New Message'), 'orange'])
except frappe.OutgoingEmailError:
pass
diff --git a/frappe/public/css/email.css b/frappe/public/css/email.css
index 3f2df6d15f..57b2033d49 100644
--- a/frappe/public/css/email.css
+++ b/frappe/public/css/email.css
@@ -121,6 +121,9 @@ hr {
.text-small {
font-size: 10px;
}
+.text-bold {
+ font-weight: bold;
+}
.indicator {
width: 8px;
height: 8px;
diff --git a/frappe/public/less/email.less b/frappe/public/less/email.less
index d4d48482ea..640c300daa 100644
--- a/frappe/public/less/email.less
+++ b/frappe/public/less/email.less
@@ -152,6 +152,10 @@ hr {
font-size: @text-small;
}
+.text-bold {
+ font-weight: bold;
+}
+
.indicator {
width: 8px;
height: 8px;
diff --git a/frappe/templates/emails/administrator_logged_in.html b/frappe/templates/emails/administrator_logged_in.html
new file mode 100644
index 0000000000..d16034bfd1
--- /dev/null
+++ b/frappe/templates/emails/administrator_logged_in.html
@@ -0,0 +1,3 @@
+{{ _("Dear System Manager,") }}
+{{ access_message }}
+{{ _("If you think this is unauthorized, please change the Administrator password.") }}
\ No newline at end of file
diff --git a/frappe/templates/emails/feedback_request_url.html b/frappe/templates/emails/feedback_request_url.html
index b6d4de7f32..e9cec87b4d 100644
--- a/frappe/templates/emails/feedback_request_url.html
+++ b/frappe/templates/emails/feedback_request_url.html
@@ -5,5 +5,5 @@
★
★
★
- {{ _("1 star being lowest & 5 stars being highest rating") }}
+ {{ _("1 star being lowest & 5 stars being highest rating") }}
diff --git a/frappe/templates/emails/new_message.html b/frappe/templates/emails/new_message.html
index a4a2ea933d..90f402f51d 100644
--- a/frappe/templates/emails/new_message.html
+++ b/frappe/templates/emails/new_message.html
@@ -1,5 +1,5 @@
-New Message
You have a new message from: {{ from }}
{{ message }}
-
-Login and view in Browser
+
diff --git a/frappe/templates/emails/upcoming_events.html b/frappe/templates/emails/upcoming_events.html
new file mode 100644
index 0000000000..8f9482b98d
--- /dev/null
+++ b/frappe/templates/emails/upcoming_events.html
@@ -0,0 +1,9 @@
+{% for e in events %}
+
+ {{ e.starts_on }}: {{ e.subject }}
+
{{ e.description or '' }}
+
+{% endfor %}
+
+ {{ _("Daily Event Digest is sent for Calendar Events where reminders are set.") }}
+
\ No newline at end of file
diff --git a/frappe/utils/jinja.py b/frappe/utils/jinja.py
index 1fd9a0d85c..749a28479f 100644
--- a/frappe/utils/jinja.py
+++ b/frappe/utils/jinja.py
@@ -28,8 +28,8 @@ def get_email_from_template(name, args):
args = args or {}
try:
message = get_template('templates/emails/' + name + '.html').render(args)
- except TemplateNotFound:
- message = None
+ except TemplateNotFound as e:
+ raise e
try:
text_content = get_template('templates/emails/' + name + '.txt').render(args)
From e7790b36d214956f64410d58145e7c426daf306d Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Thu, 27 Jul 2017 17:52:51 +0530
Subject: [PATCH 10/52] Rich Text Comment Area (#3789)
* first cut
* frappe.ui.CommentArea
* working commit
* enable airmode
* Styling fixes
* Add emoji support in comment
* editing wip
* Fixed editing area
---
frappe/public/build.json | 2 +
frappe/public/css/desk.css | 15 +
.../js/frappe/form/footer/timeline.html | 15 +-
.../public/js/frappe/form/footer/timeline.js | 168 +-
frappe/public/js/frappe/ui/comment.js | 192 +
frappe/public/js/frappe/ui/emoji.js | 4973 +++++++++++++++++
frappe/public/less/desk.less | 18 +
7 files changed, 5272 insertions(+), 111 deletions(-)
create mode 100644 frappe/public/js/frappe/ui/comment.js
create mode 100644 frappe/public/js/frappe/ui/emoji.js
diff --git a/frappe/public/build.json b/frappe/public/build.json
index 433631c0a9..b350c8151a 100755
--- a/frappe/public/build.json
+++ b/frappe/public/build.json
@@ -85,6 +85,7 @@
"public/js/frappe/dom.js",
"public/js/frappe/ui/messages.js",
"public/js/frappe/ui/keyboard.js",
+ "public/js/frappe/ui/emoji.js",
"public/js/frappe/request.js",
"public/js/frappe/socketio_client.js",
@@ -164,6 +165,7 @@
"public/js/frappe/ui/charts.js",
"public/js/frappe/ui/graph.js",
+ "public/js/frappe/ui/comment.js",
"public/js/frappe/misc/rating_icons.html",
"public/js/frappe/feedback.js"
diff --git a/frappe/public/css/desk.css b/frappe/public/css/desk.css
index 8ea2c5650f..bfce576e37 100644
--- a/frappe/public/css/desk.css
+++ b/frappe/public/css/desk.css
@@ -709,6 +709,21 @@ a.progress-small .progress-bar {
.modal .note-editor [data-original-title="Table"] {
display: none;
}
+.note-hint-popover {
+ border-radius: 3px;
+ border-color: #d1d8dd;
+ padding: 0;
+}
+.note-hint-popover .popover-content {
+ padding: 0;
+}
+.note-hint-popover .note-hint-item {
+ color: #36414C !important;
+ padding: 5px 8.8px !important;
+}
+.note-hint-popover .note-hint-item.active {
+ background-color: #F0F4F7 !important;
+}
.search-dialog .modal-dialog {
width: 768px;
}
diff --git a/frappe/public/js/frappe/form/footer/timeline.html b/frappe/public/js/frappe/form/footer/timeline.html
index 381b540300..f4f56e3371 100644
--- a/frappe/public/js/frappe/form/footer/timeline.html
+++ b/frappe/public/js/frappe/form/footer/timeline.html
@@ -1,17 +1,6 @@
-
-
-
-
+
+
{% if(doctype === "Communication") { %}
diff --git a/frappe/public/js/frappe/form/footer/timeline.js b/frappe/public/js/frappe/form/footer/timeline.js
index 3aba3290b4..7a48fa2c6f 100644
--- a/frappe/public/js/frappe/form/footer/timeline.js
+++ b/frappe/public/js/frappe/form/footer/timeline.js
@@ -14,27 +14,18 @@ frappe.ui.form.Timeline = Class.extend({
{doctype: this.frm.doctype})).appendTo(this.parent);
this.list = this.wrapper.find(".timeline-items");
- this.input = this.wrapper.find(".form-control");
- this.comment_button = this.wrapper.find(".btn-comment")
- .on("click", function() {
- me.add_comment(this);
- });
-
- this.input.keydown("meta+return ctrl+return", function(e) {
- me.comment_button.trigger("click");
- }).keyup(function(e) {
- if(me.input.val()) {
- if(me.comment_button.hasClass('btn-default')) {
- me.comment_button.removeClass('btn-default').addClass('btn-primary');
- }
- } else {
- if(me.comment_button.hasClass('btn-primary')) {
- me.comment_button.removeClass('btn-primary').addClass('btn-default');
- }
+ this.comment_area = new frappe.ui.CommentArea({
+ parent: this.wrapper.find('.timeline-head'),
+ mentions: this.get_usernames_for_mentions(),
+ on_submit: (val) => {
+ val && this.insert_comment(
+ "Comment", val, this.comment_area.button);
}
});
+ this.setup_editing_area();
+
this.setup_email_button();
this.list.on("click", ".toggle-blockquote", function() {
@@ -43,8 +34,6 @@ frappe.ui.form.Timeline = Class.extend({
this.setup_comment_like();
- this.setup_mentions();
-
this.list.on("click", ".btn-more", function() {
var communications = me.get_communications();
frappe.call({
@@ -94,13 +83,25 @@ frappe.ui.form.Timeline = Class.extend({
});
} else {
$.extend(args, {
- txt: frappe.markdown(me.input.val())
+ txt: frappe.markdown(me.comment_area.val())
});
}
new frappe.views.CommunicationComposer(args)
});
},
+ setup_editing_area: function() {
+ this.$editing_area = $('');
+
+ this.editing_area = new frappe.ui.CommentArea({
+ parent: this.$editing_area,
+ mentions: this.get_usernames_for_mentions(),
+ no_wrapper: true
+ });
+
+ this.editing_area.destroy();
+ },
+
refresh: function(scroll_to_end) {
var me = this;
@@ -112,7 +113,7 @@ frappe.ui.form.Timeline = Class.extend({
}
this.wrapper.toggle(true);
this.list.empty();
- this.input.val('');
+ this.comment_area.val('');
var communications = this.get_communications(true);
@@ -130,7 +131,7 @@ frappe.ui.form.Timeline = Class.extend({
}
if (this.more) {
- var $more = $('
\
+ $('
\
More \
').appendTo(me.list);
}
@@ -161,43 +162,45 @@ frappe.ui.form.Timeline = Class.extend({
.on("click", ".close", function() {
var name = $timeline_item.data('name');
me.delete_comment(name);
-
return false;
})
- .on('click', '.edit', function() {
- var is_editing = 'is-editing';
- var content = $timeline_item.find('.timeline-item-content');
+ .on('click', '.edit', function(e) {
+ e.preventDefault();
var name = $timeline_item.data('name');
- var update_comment = function() {
- var val = content.find('textarea').val();
- // set content to new val so that on save and refresh the new content is shown
- c.content = val;
-
- frappe.timeline.update_communication(c);
- me.update_comment(name, val);
-
- // all changes to the timeline_item for editing are reset after calling refresh
- me.refresh();
- }
-
- if(content.hasClass(is_editing)) {
- update_comment();
+ if($timeline_item.hasClass('is-editing')) {
+ me.editing_area.submit();
+ me.$editing_area.detach();
} else {
var $edit_btn = $(this);
- var editing_textarea = me.input.clone()
- .removeClass('comment-input');
-
- editing_textarea.keydown("meta+return ctrl+return", function(e) {
- update_comment();
- });
-
- frappe.db.get_value('Communication', {name: name}, 'content', function(r) {
- $edit_btn.find('i').removeClass('octicon-pencil').addClass('octicon-check');
- editing_textarea.val(r.content);
- content.html(editing_textarea);
- content.addClass(is_editing);
- });
+ var content = $timeline_item.find('.timeline-item-content').html();
+
+ $edit_btn
+ .find('i')
+ .removeClass('octicon-pencil')
+ .addClass('octicon-check');
+
+ me.editing_area.setup_summernote();
+ me.editing_area.val(content);
+ me.editing_area.on_submit = (value) => {
+ me.editing_area.destroy();
+ value = value.trim();
+ // set content to new val so that on save and refresh the new content is shown
+ c.content = value;
+ frappe.timeline.update_communication(c);
+ me.update_comment(name, value);
+ // all changes to the timeline_item for editing are reset after calling refresh
+ me.refresh();
+ };
+
+ $timeline_item
+ .find('.timeline-item-content')
+ .hide();
+ $timeline_item
+ .find('.timeline-content-show')
+ .append(me.$editing_area);
+ $timeline_item
+ .addClass('is-editing');
}
return false;
@@ -295,11 +298,14 @@ frappe.ui.form.Timeline = Class.extend({
} else {
c.content_html = c.content;
c.content_html = frappe.utils.strip_whitespace(c.content_html);
- c.content_html = c.content_html.replace(/</g,"<").replace(/>/g,">")
+ c.content_html = c.content_html.replace(/</g,"<").replace(/>/g,">");
}
// bold @mentions
- if(c.comment_type==="Comment") {
+ if(c.comment_type==="Comment" &&
+ // avoid adding
tag a 2nd time
+ !c.content_html.match(/(^|\W)(@\w+)<\/b>/)
+ ) {
c.content_html = c.content_html.replace(/(^|\W)(@\w+)/g, "$1$2 ");
}
@@ -519,16 +525,8 @@ frappe.ui.form.Timeline = Class.extend({
};
},
- add_comment: function(btn) {
- var txt = this.input.val();
-
- if(txt) {
- this.insert_comment("Comment", txt, btn, this.input);
- }
- },
- insert_comment: function(comment_type, comment, btn, input) {
+ insert_comment: function(comment_type, comment, btn) {
var me = this;
- if(input) input.prop('disabled', true);
return frappe.call({
method: "frappe.desk.form.utils.add_comment",
args: {
@@ -545,8 +543,7 @@ frappe.ui.form.Timeline = Class.extend({
btn: btn,
callback: function(r) {
if(!r.exc) {
- me.input.val("");
-
+ me.comment_area.val('');
frappe.utils.play_sound("click");
var comment = r.message;
@@ -565,9 +562,6 @@ frappe.ui.form.Timeline = Class.extend({
me.frm.get_docinfo().communications = comments.concat([r.message]);
me.refresh(true);
}
- },
- always: function() {
- if(input) input.prop('disabled', false);
}
});
@@ -620,7 +614,9 @@ frappe.ui.form.Timeline = Class.extend({
fieldname: 'content',
value: content,
}, callback: function(r) {
- frappe.utils.play_sound('click');
+ if(!r.exc) {
+ frappe.utils.play_sound('click');
+ }
}
});
},
@@ -655,35 +651,11 @@ frappe.ui.form.Timeline = Class.extend({
return last_email;
},
- setup_mentions: function() {
- this.setup_awesomplete_for_mentions();
- },
+ get_usernames_for_mentions: function() {
+ var valid_users = Object.keys(frappe.boot.user_info)
+ .filter(user => !["Administrator", "Guest"].includes(user));
- setup_awesomplete_for_mentions: function() {
- var me = this;
- var username_user_map = {};
- for (var name in frappe.boot.user_info) {
- if(name !== "Administrator" && name !== "Guest") {
- var _user = frappe.boot.user_info[name];
- username_user_map[_user.username] = _user;
- }
- }
- var source = Object.keys(username_user_map);
-
- this.awesomplete = new Awesomplete(this.input.get(0), {
- minChars: 0,
- maxItems: 99,
- autoFirst: true,
- list: source,
- filter: function(text, input) {
- if(input.indexOf("@") === -1) return false;
- return Awesomplete.FILTER_STARTSWITH(text, input.match(/[^@]*$/)[0]);
- },
- replace: function(text) {
- var before = this.input.value.match(/^.*@\s*|/)[0];
- this.input.value = before + text + " ";
- }
- });
+ return valid_users.map(user => frappe.boot.user_info[user].username);
},
setup_comment_like: function() {
diff --git a/frappe/public/js/frappe/ui/comment.js b/frappe/public/js/frappe/ui/comment.js
new file mode 100644
index 0000000000..e37724ddb3
--- /dev/null
+++ b/frappe/public/js/frappe/ui/comment.js
@@ -0,0 +1,192 @@
+/**
+ * CommentArea: A small rich text editor with
+ * support for @mentions and :emojis:
+ * @example
+ * let comment_area = new frappe.ui.CommentArea({
+ * parent: '.comment-area',
+ * mentions: ['john', 'mary', 'kate'],
+ * on_submit: (value) => save_to_database(value)
+ * });
+ */
+
+frappe.ui.CommentArea = class CommentArea {
+
+ constructor({ parent = null, mentions = [], on_submit = null, no_wrapper = false }) {
+ this.parent = $(parent);
+ this.mentions = mentions;
+ this.on_submit = on_submit;
+ this.no_wrapper = no_wrapper;
+
+ this.make();
+ }
+
+ make() {
+ this.setup_dom();
+ this.setup_summernote();
+ this.bind_events();
+ }
+
+ setup_dom() {
+ const header = !this.no_wrapper ?
+ `` : '';
+
+ const footer = !this.no_wrapper ?
+ `
+ ${__("Ctrl+Enter to add comment")}
+
` : '';
+
+ this.wrapper = $(`
+
+ `);
+ this.wrapper.appendTo(this.parent);
+ this.input = this.parent.find('.comment-input');
+ this.button = this.parent.find('.btn-comment');
+ }
+
+ setup_summernote() {
+ const { input, button } = this;
+
+ input.summernote({
+ height: 100,
+ toolbar: false,
+ airMode: true,
+ hint: {
+ mentions: this.mentions,
+ match: /\B([@:]\w*)/,
+ search: function (keyword, callback) {
+ let items = [];
+ if (keyword.startsWith('@')) {
+ keyword = keyword.substr(1);
+ items = this.mentions;
+ } else if (keyword.startsWith(':')) {
+ items = frappe.ui.emoji_keywords
+ .filter(k => k.startsWith(keyword))
+ .slice(0, 7);
+ }
+ callback($.grep(items, function (item) {
+ return item.indexOf(keyword) == 0;
+ }));
+ },
+ template: function (item) {
+ if (item.startsWith(':')) {
+ return frappe.ui.get_emoji(item) + ' ' + item;
+ } else {
+ return item;
+ }
+ },
+ content: function (item) {
+ if(item.startsWith(':')) {
+ return frappe.ui.get_emoji(item);
+ } else {
+ return '@' + item;
+ }
+ }
+ },
+ callbacks: {
+ onChange: () => {
+ if(input.summernote('isEmpty')) {
+ button
+ .removeClass('btn-primary')
+ .addClass('btn-default');
+ } else {
+ button
+ .removeClass('btn-default')
+ .addClass('btn-primary');
+ }
+ },
+ onKeydown: (e) => {
+ var key = frappe.ui.keys.get_key(e);
+ if(key === 'ctrl+enter') {
+ e.preventDefault();
+ this.submit();
+ }
+ e.stopPropagation();
+ },
+ },
+ icons: {
+ 'align': 'fa fa-align',
+ 'alignCenter': 'fa fa-align-center',
+ 'alignJustify': 'fa fa-align-justify',
+ 'alignLeft': 'fa fa-align-left',
+ 'alignRight': 'fa fa-align-right',
+ 'indent': 'fa fa-indent',
+ 'outdent': 'fa fa-outdent',
+ 'arrowsAlt': 'fa fa-arrows-alt',
+ 'bold': 'fa fa-bold',
+ 'caret': 'caret',
+ 'circle': 'fa fa-circle',
+ 'close': 'fa fa-close',
+ 'code': 'fa fa-code',
+ 'eraser': 'fa fa-eraser',
+ 'font': 'fa fa-font',
+ 'frame': 'fa fa-frame',
+ 'italic': 'fa fa-italic',
+ 'link': 'fa fa-link',
+ 'unlink': 'fa fa-chain-broken',
+ 'magic': 'fa fa-magic',
+ 'menuCheck': 'fa fa-check',
+ 'minus': 'fa fa-minus',
+ 'orderedlist': 'fa fa-list-ol',
+ 'pencil': 'fa fa-pencil',
+ 'picture': 'fa fa-image',
+ 'question': 'fa fa-question',
+ 'redo': 'fa fa-redo',
+ 'square': 'fa fa-square',
+ 'strikethrough': 'fa fa-strikethrough',
+ 'subscript': 'fa fa-subscript',
+ 'superscript': 'fa fa-superscript',
+ 'table': 'fa fa-table',
+ 'textHeight': 'fa fa-text-height',
+ 'trash': 'fa fa-trash',
+ 'underline': 'fa fa-underline',
+ 'undo': 'fa fa-undo',
+ 'unorderedlist': 'fa fa-list-ul',
+ 'video': 'fa fa-video-camera'
+ }
+ });
+
+ this.note_editor = this.wrapper.find('.note-editor');
+ this.note_editor.css({
+ 'border': '1px solid #ebeff2',
+ 'border-radius': '3px',
+ 'padding': '10px',
+ 'margin-bottom': '10px',
+ 'min-height': '80px',
+ 'cursor': 'text'
+ });
+ this.note_editor.on('click', () => input.summernote('focus'));
+ }
+
+ destroy() {
+ this.input.summernote('destroy');
+ }
+
+ bind_events() {
+ this.button.on('click', this.submit.bind(this));
+ }
+
+ val(value) {
+ // Return html if no value specified
+ if(value === undefined) {
+ return this.input.summernote('code');
+ }
+ // Set html if value is specified
+ this.input.summernote('code', value);
+ }
+
+ submit() {
+ // Pass comment's value (html) to submit handler
+ this.on_submit && this.on_submit(this.val());
+ }
+};
diff --git a/frappe/public/js/frappe/ui/emoji.js b/frappe/public/js/frappe/ui/emoji.js
new file mode 100644
index 0000000000..f70fc926cb
--- /dev/null
+++ b/frappe/public/js/frappe/ui/emoji.js
@@ -0,0 +1,4973 @@
+frappe.ui.get_emoji = function(keyword) {
+ if (!keyword.includes(':'))
+ keyword = ':' + keyword + ':';
+ return frappe.ui.emoji_map[keyword];
+};
+
+frappe.ui.emojis = [
+ "🀄",
+ "🃏",
+ "🅰",
+ "🅱",
+ "🅾",
+ "🅿",
+ "🆎",
+ "🆑",
+ "🆒",
+ "🆓",
+ "🆔",
+ "🆕",
+ "🆖",
+ "🆗",
+ "🆘",
+ "🆙",
+ "🆚",
+ "🇦🇨",
+ "🇦🇩",
+ "🇦🇪",
+ "🇦🇫",
+ "🇦🇬",
+ "🇦🇮",
+ "🇦🇱",
+ "🇦🇲",
+ "🇦🇴",
+ "🇦🇶",
+ "🇦🇷",
+ "🇦🇸",
+ "🇦🇹",
+ "🇦🇺",
+ "🇦🇼",
+ "🇦🇽",
+ "🇦🇿",
+ "🇦",
+ "🇧🇦",
+ "🇧🇧",
+ "🇧🇩",
+ "🇧🇪",
+ "🇧🇫",
+ "🇧🇬",
+ "🇧🇭",
+ "🇧🇮",
+ "🇧🇯",
+ "🇧🇱",
+ "🇧🇲",
+ "🇧🇳",
+ "🇧🇴",
+ "🇧🇶",
+ "🇧🇷",
+ "🇧🇸",
+ "🇧🇹",
+ "🇧🇻",
+ "🇧🇼",
+ "🇧🇾",
+ "🇧🇿",
+ "🇧",
+ "🇨🇦",
+ "🇨🇨",
+ "🇨🇩",
+ "🇨🇫",
+ "🇨🇬",
+ "🇨🇭",
+ "🇨🇮",
+ "🇨🇰",
+ "🇨🇱",
+ "🇨🇲",
+ "🇨🇳",
+ "🇨🇴",
+ "🇨🇵",
+ "🇨🇷",
+ "🇨🇺",
+ "🇨🇻",
+ "🇨🇼",
+ "🇨🇽",
+ "🇨🇾",
+ "🇨🇿",
+ "🇨",
+ "🇩🇪",
+ "🇩🇬",
+ "🇩🇯",
+ "🇩🇰",
+ "🇩🇲",
+ "🇩🇴",
+ "🇩🇿",
+ "🇩",
+ "🇪🇦",
+ "🇪🇨",
+ "🇪🇪",
+ "🇪🇬",
+ "🇪🇭",
+ "🇪🇷",
+ "🇪🇸",
+ "🇪🇹",
+ "🇪🇺",
+ "🇪",
+ "🇫🇮",
+ "🇫🇯",
+ "🇫🇰",
+ "🇫🇲",
+ "🇫🇴",
+ "🇫🇷",
+ "🇫",
+ "🇬🇦",
+ "🇬🇧",
+ "🇬🇩",
+ "🇬🇪",
+ "🇬🇫",
+ "🇬🇬",
+ "🇬🇭",
+ "🇬🇮",
+ "🇬🇱",
+ "🇬🇲",
+ "🇬🇳",
+ "🇬🇵",
+ "🇬🇶",
+ "🇬🇷",
+ "🇬🇸",
+ "🇬🇹",
+ "🇬🇺",
+ "🇬🇼",
+ "🇬🇾",
+ "🇬",
+ "🇭🇰",
+ "🇭🇲",
+ "🇭🇳",
+ "🇭🇷",
+ "🇭🇹",
+ "🇭🇺",
+ "🇭",
+ "🇮🇨",
+ "🇮🇩",
+ "🇮🇪",
+ "🇮🇱",
+ "🇮🇲",
+ "🇮🇳",
+ "🇮🇴",
+ "🇮🇶",
+ "🇮🇷",
+ "🇮🇸",
+ "🇮🇹",
+ "🇮",
+ "🇯🇪",
+ "🇯🇲",
+ "🇯🇴",
+ "🇯🇵",
+ "🇯",
+ "🇰🇪",
+ "🇰🇬",
+ "🇰🇭",
+ "🇰🇮",
+ "🇰🇲",
+ "🇰🇳",
+ "🇰🇵",
+ "🇰🇷",
+ "🇰🇼",
+ "🇰🇾",
+ "🇰🇿",
+ "🇰",
+ "🇱🇦",
+ "🇱🇧",
+ "🇱🇨",
+ "🇱🇮",
+ "🇱🇰",
+ "🇱🇷",
+ "🇱🇸",
+ "🇱🇹",
+ "🇱🇺",
+ "🇱🇻",
+ "🇱🇾",
+ "🇱",
+ "🇲🇦",
+ "🇲🇨",
+ "🇲🇩",
+ "🇲🇪",
+ "🇲🇫",
+ "🇲🇬",
+ "🇲🇭",
+ "🇲🇰",
+ "🇲🇱",
+ "🇲🇲",
+ "🇲🇳",
+ "🇲🇴",
+ "🇲🇵",
+ "🇲🇶",
+ "🇲🇷",
+ "🇲🇸",
+ "🇲🇹",
+ "🇲🇺",
+ "🇲🇻",
+ "🇲🇼",
+ "🇲🇽",
+ "🇲🇾",
+ "🇲🇿",
+ "🇲",
+ "🇳🇦",
+ "🇳🇨",
+ "🇳🇪",
+ "🇳🇫",
+ "🇳🇬",
+ "🇳🇮",
+ "🇳🇱",
+ "🇳🇴",
+ "🇳🇵",
+ "🇳🇷",
+ "🇳🇺",
+ "🇳🇿",
+ "🇳",
+ "🇴🇲",
+ "🇴",
+ "🇵🇦",
+ "🇵🇪",
+ "🇵🇫",
+ "🇵🇬",
+ "🇵🇭",
+ "🇵🇰",
+ "🇵🇱",
+ "🇵🇲",
+ "🇵🇳",
+ "🇵🇷",
+ "🇵🇸",
+ "🇵🇹",
+ "🇵🇼",
+ "🇵🇾",
+ "🇵",
+ "🇶🇦",
+ "🇶",
+ "🇷🇪",
+ "🇷🇴",
+ "🇷🇸",
+ "🇷🇺",
+ "🇷🇼",
+ "🇷",
+ "🇸🇦",
+ "🇸🇧",
+ "🇸🇨",
+ "🇸🇩",
+ "🇸🇪",
+ "🇸🇬",
+ "🇸🇭",
+ "🇸🇮",
+ "🇸🇯",
+ "🇸🇰",
+ "🇸🇱",
+ "🇸🇲",
+ "🇸🇳",
+ "🇸🇴",
+ "🇸🇷",
+ "🇸🇸",
+ "🇸🇹",
+ "🇸🇻",
+ "🇸🇽",
+ "🇸🇾",
+ "🇸🇿",
+ "🇸",
+ "🇹🇦",
+ "🇹🇨",
+ "🇹🇩",
+ "🇹🇫",
+ "🇹🇬",
+ "🇹🇭",
+ "🇹🇯",
+ "🇹🇰",
+ "🇹🇱",
+ "🇹🇲",
+ "🇹🇳",
+ "🇹🇴",
+ "🇹🇷",
+ "🇹🇹",
+ "🇹🇻",
+ "🇹🇼",
+ "🇹🇿",
+ "🇹",
+ "🇺🇦",
+ "🇺🇬",
+ "🇺🇲",
+ "🇺🇳",
+ "🇺🇸",
+ "🇺🇾",
+ "🇺🇿",
+ "🇺",
+ "🇻🇦",
+ "🇻🇨",
+ "🇻🇪",
+ "🇻🇬",
+ "🇻🇮",
+ "🇻🇳",
+ "🇻🇺",
+ "🇻",
+ "🇼🇫",
+ "🇼🇸",
+ "🇼",
+ "🇽🇰",
+ "🇽",
+ "🇾🇪",
+ "🇾🇹",
+ "🇾",
+ "🇿🇦",
+ "🇿🇲",
+ "🇿🇼",
+ "🇿",
+ "🈁",
+ "🈂",
+ "🈚",
+ "🈯",
+ "🈲",
+ "🈳",
+ "🈴",
+ "🈵",
+ "🈶",
+ "🈷",
+ "🈸",
+ "🈹",
+ "🈺",
+ "🉐",
+ "🉑",
+ "🌀",
+ "🌁",
+ "🌂",
+ "🌃",
+ "🌄",
+ "🌅",
+ "🌆",
+ "🌇",
+ "🌈",
+ "🌉",
+ "🌊",
+ "🌋",
+ "🌌",
+ "🌍",
+ "🌎",
+ "🌏",
+ "🌐",
+ "🌑",
+ "🌒",
+ "🌓",
+ "🌔",
+ "🌕",
+ "🌖",
+ "🌗",
+ "🌘",
+ "🌙",
+ "🌚",
+ "🌛",
+ "🌜",
+ "🌝",
+ "🌞",
+ "🌟",
+ "🌠",
+ "🌡",
+ "🌤",
+ "🌥",
+ "🌦",
+ "🌧",
+ "🌨",
+ "🌩",
+ "🌪",
+ "🌫",
+ "🌬",
+ "🌭",
+ "🌮",
+ "🌯",
+ "🌰",
+ "🌱",
+ "🌲",
+ "🌳",
+ "🌴",
+ "🌵",
+ "🌶",
+ "🌷",
+ "🌸",
+ "🌹",
+ "🌺",
+ "🌻",
+ "🌼",
+ "🌽",
+ "🌾",
+ "🌿",
+ "🍀",
+ "🍁",
+ "🍂",
+ "🍃",
+ "🍄",
+ "🍅",
+ "🍆",
+ "🍇",
+ "🍈",
+ "🍉",
+ "🍊",
+ "🍋",
+ "🍌",
+ "🍍",
+ "🍎",
+ "🍏",
+ "🍐",
+ "🍑",
+ "🍒",
+ "🍓",
+ "🍔",
+ "🍕",
+ "🍖",
+ "🍗",
+ "🍘",
+ "🍙",
+ "🍚",
+ "🍛",
+ "🍜",
+ "🍝",
+ "🍞",
+ "🍟",
+ "🍠",
+ "🍡",
+ "🍢",
+ "🍣",
+ "🍤",
+ "🍥",
+ "🍦",
+ "🍧",
+ "🍨",
+ "🍩",
+ "🍪",
+ "🍫",
+ "🍬",
+ "🍭",
+ "🍮",
+ "🍯",
+ "🍰",
+ "🍱",
+ "🍲",
+ "🍳",
+ "🍴",
+ "🍵",
+ "🍶",
+ "🍷",
+ "🍸",
+ "🍹",
+ "🍺",
+ "🍻",
+ "🍼",
+ "🍽",
+ "🍾",
+ "🍿",
+ "🎀",
+ "🎁",
+ "🎂",
+ "🎃",
+ "🎄",
+ "🎅🏻",
+ "🎅🏼",
+ "🎅🏽",
+ "🎅🏾",
+ "🎅🏿",
+ "🎅",
+ "🎆",
+ "🎇",
+ "🎈",
+ "🎉",
+ "🎊",
+ "🎋",
+ "🎌",
+ "🎍",
+ "🎎",
+ "🎏",
+ "🎐",
+ "🎑",
+ "🎒",
+ "🎓",
+ "🎖",
+ "🎗",
+ "🎙",
+ "🎚",
+ "🎛",
+ "🎞",
+ "🎟",
+ "🎠",
+ "🎡",
+ "🎢",
+ "🎣",
+ "🎤",
+ "🎥",
+ "🎦",
+ "🎧",
+ "🎨",
+ "🎩",
+ "🎪",
+ "🎫",
+ "🎬",
+ "🎭",
+ "🎮",
+ "🎯",
+ "🎰",
+ "🎱",
+ "🎲",
+ "🎳",
+ "🎴",
+ "🎵",
+ "🎶",
+ "🎷",
+ "🎸",
+ "🎹",
+ "🎺",
+ "🎻",
+ "🎼",
+ "🎽",
+ "🎾",
+ "🎿",
+ "🏀",
+ "🏁",
+ "🏂🏻",
+ "🏂🏼",
+ "🏂🏽",
+ "🏂🏾",
+ "🏂🏿",
+ "🏂",
+ "🏃🏻♀️",
+ "🏃🏻♂️",
+ "🏃🏻",
+ "🏃🏼♀️",
+ "🏃🏼♂️",
+ "🏃🏼",
+ "🏃🏽♀️",
+ "🏃🏽♂️",
+ "🏃🏽",
+ "🏃🏾♀️",
+ "🏃🏾♂️",
+ "🏃🏾",
+ "🏃🏿♀️",
+ "🏃🏿♂️",
+ "🏃🏿",
+ "🏃♀️",
+ "🏃♂️",
+ "🏃",
+ "🏄🏻♀️",
+ "🏄🏻♂️",
+ "🏄🏻",
+ "🏄🏼♀️",
+ "🏄🏼♂️",
+ "🏄🏼",
+ "🏄🏽♀️",
+ "🏄🏽♂️",
+ "🏄🏽",
+ "🏄🏾♀️",
+ "🏄🏾♂️",
+ "🏄🏾",
+ "🏄🏿♀️",
+ "🏄🏿♂️",
+ "🏄🏿",
+ "🏄♀️",
+ "🏄♂️",
+ "🏄",
+ "🏅",
+ "🏆",
+ "🏇🏻",
+ "🏇🏼",
+ "🏇🏽",
+ "🏇🏾",
+ "🏇🏿",
+ "🏇",
+ "🏈",
+ "🏉",
+ "🏊🏻♀️",
+ "🏊🏻♂️",
+ "🏊🏻",
+ "🏊🏼♀️",
+ "🏊🏼♂️",
+ "🏊🏼",
+ "🏊🏽♀️",
+ "🏊🏽♂️",
+ "🏊🏽",
+ "🏊🏾♀️",
+ "🏊🏾♂️",
+ "🏊🏾",
+ "🏊🏿♀️",
+ "🏊🏿♂️",
+ "🏊🏿",
+ "🏊♀️",
+ "🏊♂️",
+ "🏊",
+ "🏋🏻♀️",
+ "🏋🏻♂️",
+ "🏋🏻",
+ "🏋🏼♀️",
+ "🏋🏼♂️",
+ "🏋🏼",
+ "🏋🏽♀️",
+ "🏋🏽♂️",
+ "🏋🏽",
+ "🏋🏾♀️",
+ "🏋🏾♂️",
+ "🏋🏾",
+ "🏋🏿♀️",
+ "🏋🏿♂️",
+ "🏋🏿",
+ "🏋️♀️",
+ "🏋️♂️",
+ "🏋",
+ "🏌🏻♀️",
+ "🏌🏻♂️",
+ "🏌🏻",
+ "🏌🏼♀️",
+ "🏌🏼♂️",
+ "🏌🏼",
+ "🏌🏽♀️",
+ "🏌🏽♂️",
+ "🏌🏽",
+ "🏌🏾♀️",
+ "🏌🏾♂️",
+ "🏌🏾",
+ "🏌🏿♀️",
+ "🏌🏿♂️",
+ "🏌🏿",
+ "🏌️♀️",
+ "🏌️♂️",
+ "🏌",
+ "🏍",
+ "🏎",
+ "🏏",
+ "🏐",
+ "🏑",
+ "🏒",
+ "🏓",
+ "🏔",
+ "🏕",
+ "🏖",
+ "🏗",
+ "🏘",
+ "🏙",
+ "🏚",
+ "🏛",
+ "🏜",
+ "🏝",
+ "🏞",
+ "🏟",
+ "🏠",
+ "🏡",
+ "🏢",
+ "🏣",
+ "🏤",
+ "🏥",
+ "🏦",
+ "🏧",
+ "🏨",
+ "🏩",
+ "🏪",
+ "🏫",
+ "🏬",
+ "🏭",
+ "🏮",
+ "🏯",
+ "🏰",
+ "🏳️🌈",
+ "🏳",
+ "🏴☠️",
+ "🏴",
+ "🏵",
+ "🏷",
+ "🏸",
+ "🏹",
+ "🏺",
+ "🏻",
+ "🏼",
+ "🏽",
+ "🏾",
+ "🏿",
+ "🐀",
+ "🐁",
+ "🐂",
+ "🐃",
+ "🐄",
+ "🐅",
+ "🐆",
+ "🐇",
+ "🐈",
+ "🐉",
+ "🐊",
+ "🐋",
+ "🐌",
+ "🐍",
+ "🐎",
+ "🐏",
+ "🐐",
+ "🐑",
+ "🐒",
+ "🐓",
+ "🐔",
+ "🐕",
+ "🐖",
+ "🐗",
+ "🐘",
+ "🐙",
+ "🐚",
+ "🐛",
+ "🐜",
+ "🐝",
+ "🐞",
+ "🐟",
+ "🐠",
+ "🐡",
+ "🐢",
+ "🐣",
+ "🐤",
+ "🐥",
+ "🐦",
+ "🐧",
+ "🐨",
+ "🐩",
+ "🐪",
+ "🐫",
+ "🐬",
+ "🐭",
+ "🐮",
+ "🐯",
+ "🐰",
+ "🐱",
+ "🐲",
+ "🐳",
+ "🐴",
+ "🐵",
+ "🐶",
+ "🐷",
+ "🐸",
+ "🐹",
+ "🐺",
+ "🐻",
+ "🐼",
+ "🐽",
+ "🐾",
+ "🐿",
+ "👀",
+ "👁🗨",
+ "👁",
+ "👂🏻",
+ "👂🏼",
+ "👂🏽",
+ "👂🏾",
+ "👂🏿",
+ "👂",
+ "👃🏻",
+ "👃🏼",
+ "👃🏽",
+ "👃🏾",
+ "👃🏿",
+ "👃",
+ "👄",
+ "👅",
+ "👆🏻",
+ "👆🏼",
+ "👆🏽",
+ "👆🏾",
+ "👆🏿",
+ "👆",
+ "👇🏻",
+ "👇🏼",
+ "👇🏽",
+ "👇🏾",
+ "👇🏿",
+ "👇",
+ "👈🏻",
+ "👈🏼",
+ "👈🏽",
+ "👈🏾",
+ "👈🏿",
+ "👈",
+ "👉🏻",
+ "👉🏼",
+ "👉🏽",
+ "👉🏾",
+ "👉🏿",
+ "👉",
+ "👊🏻",
+ "👊🏼",
+ "👊🏽",
+ "👊🏾",
+ "👊🏿",
+ "👊",
+ "👋🏻",
+ "👋🏼",
+ "👋🏽",
+ "👋🏾",
+ "👋🏿",
+ "👋",
+ "👌🏻",
+ "👌🏼",
+ "👌🏽",
+ "👌🏾",
+ "👌🏿",
+ "👌",
+ "👍🏻",
+ "👍🏼",
+ "👍🏽",
+ "👍🏾",
+ "👍🏿",
+ "👍",
+ "👎🏻",
+ "👎🏼",
+ "👎🏽",
+ "👎🏾",
+ "👎🏿",
+ "👎",
+ "👏🏻",
+ "👏🏼",
+ "👏🏽",
+ "👏🏾",
+ "👏🏿",
+ "👏",
+ "👐🏻",
+ "👐🏼",
+ "👐🏽",
+ "👐🏾",
+ "👐🏿",
+ "👐",
+ "👑",
+ "👒",
+ "👓",
+ "👔",
+ "👕",
+ "👖",
+ "👗",
+ "👘",
+ "👙",
+ "👚",
+ "👛",
+ "👜",
+ "👝",
+ "👞",
+ "👟",
+ "👠",
+ "👡",
+ "👢",
+ "👣",
+ "👤",
+ "👥",
+ "👦🏻",
+ "👦🏼",
+ "👦🏽",
+ "👦🏾",
+ "👦🏿",
+ "👦",
+ "👧🏻",
+ "👧🏼",
+ "👧🏽",
+ "👧🏾",
+ "👧🏿",
+ "👧",
+ "👨🏻🌾",
+ "👨🏻🍳",
+ "👨🏻🎓",
+ "👨🏻🎤",
+ "👨🏻🎨",
+ "👨🏻🏫",
+ "👨🏻🏭",
+ "👨🏻💻",
+ "👨🏻💼",
+ "👨🏻🔧",
+ "👨🏻🔬",
+ "👨🏻🚀",
+ "👨🏻🚒",
+ "👨🏻⚕️",
+ "👨🏻⚖️",
+ "👨🏻✈️",
+ "👨🏻",
+ "👨🏼🌾",
+ "👨🏼🍳",
+ "👨🏼🎓",
+ "👨🏼🎤",
+ "👨🏼🎨",
+ "👨🏼🏫",
+ "👨🏼🏭",
+ "👨🏼💻",
+ "👨🏼💼",
+ "👨🏼🔧",
+ "👨🏼🔬",
+ "👨🏼🚀",
+ "👨🏼🚒",
+ "👨🏼⚕️",
+ "👨🏼⚖️",
+ "👨🏼✈️",
+ "👨🏼",
+ "👨🏽🌾",
+ "👨🏽🍳",
+ "👨🏽🎓",
+ "👨🏽🎤",
+ "👨🏽🎨",
+ "👨🏽🏫",
+ "👨🏽🏭",
+ "👨🏽💻",
+ "👨🏽💼",
+ "👨🏽🔧",
+ "👨🏽🔬",
+ "👨🏽🚀",
+ "👨🏽🚒",
+ "👨🏽⚕️",
+ "👨🏽⚖️",
+ "👨🏽✈️",
+ "👨🏽",
+ "👨🏾🌾",
+ "👨🏾🍳",
+ "👨🏾🎓",
+ "👨🏾🎤",
+ "👨🏾🎨",
+ "👨🏾🏫",
+ "👨🏾🏭",
+ "👨🏾💻",
+ "👨🏾💼",
+ "👨🏾🔧",
+ "👨🏾🔬",
+ "👨🏾🚀",
+ "👨🏾🚒",
+ "👨🏾⚕️",
+ "👨🏾⚖️",
+ "👨🏾✈️",
+ "👨🏾",
+ "👨🏿🌾",
+ "👨🏿🍳",
+ "👨🏿🎓",
+ "👨🏿🎤",
+ "👨🏿🎨",
+ "👨🏿🏫",
+ "👨🏿🏭",
+ "👨🏿💻",
+ "👨🏿💼",
+ "👨🏿🔧",
+ "👨🏿🔬",
+ "👨🏿🚀",
+ "👨🏿🚒",
+ "👨🏿⚕️",
+ "👨🏿⚖️",
+ "👨🏿✈️",
+ "👨🏿",
+ "👨🌾",
+ "👨🍳",
+ "👨🎓",
+ "👨🎤",
+ "👨🎨",
+ "👨🏫",
+ "👨🏭",
+ "👨👦👦",
+ "👨👦",
+ "👨👧👦",
+ "👨👧👧",
+ "👨👧",
+ "👨👨👦👦",
+ "👨👨👦",
+ "👨👨👧👦",
+ "👨👨👧👧",
+ "👨👨👧",
+ "👨👩👦👦",
+ "👨👩👦",
+ "👨👩👧👦",
+ "👨👩👧👧",
+ "👨👩👧",
+ "👨💻",
+ "👨💼",
+ "👨🔧",
+ "👨🔬",
+ "👨🚀",
+ "👨🚒",
+ "👨⚕️",
+ "👨⚖️",
+ "👨✈️",
+ "👨❤️👨",
+ "👨❤️💋👨",
+ "👨",
+ "👩🏻🌾",
+ "👩🏻🍳",
+ "👩🏻🎓",
+ "👩🏻🎤",
+ "👩🏻🎨",
+ "👩🏻🏫",
+ "👩🏻🏭",
+ "👩🏻💻",
+ "👩🏻💼",
+ "👩🏻🔧",
+ "👩🏻🔬",
+ "👩🏻🚀",
+ "👩🏻🚒",
+ "👩🏻⚕️",
+ "👩🏻⚖️",
+ "👩🏻✈️",
+ "👩🏻",
+ "👩🏼🌾",
+ "👩🏼🍳",
+ "👩🏼🎓",
+ "👩🏼🎤",
+ "👩🏼🎨",
+ "👩🏼🏫",
+ "👩🏼🏭",
+ "👩🏼💻",
+ "👩🏼💼",
+ "👩🏼🔧",
+ "👩🏼🔬",
+ "👩🏼🚀",
+ "👩🏼🚒",
+ "👩🏼⚕️",
+ "👩🏼⚖️",
+ "👩🏼✈️",
+ "👩🏼",
+ "👩🏽🌾",
+ "👩🏽🍳",
+ "👩🏽🎓",
+ "👩🏽🎤",
+ "👩🏽🎨",
+ "👩🏽🏫",
+ "👩🏽🏭",
+ "👩🏽💻",
+ "👩🏽💼",
+ "👩🏽🔧",
+ "👩🏽🔬",
+ "👩🏽🚀",
+ "👩🏽🚒",
+ "👩🏽⚕️",
+ "👩🏽⚖️",
+ "👩🏽✈️",
+ "👩🏽",
+ "👩🏾🌾",
+ "👩🏾🍳",
+ "👩🏾🎓",
+ "👩🏾🎤",
+ "👩🏾🎨",
+ "👩🏾🏫",
+ "👩🏾🏭",
+ "👩🏾💻",
+ "👩🏾💼",
+ "👩🏾🔧",
+ "👩🏾🔬",
+ "👩🏾🚀",
+ "👩🏾🚒",
+ "👩🏾⚕️",
+ "👩🏾⚖️",
+ "👩🏾✈️",
+ "👩🏾",
+ "👩🏿🌾",
+ "👩🏿🍳",
+ "👩🏿🎓",
+ "👩🏿🎤",
+ "👩🏿🎨",
+ "👩🏿🏫",
+ "👩🏿🏭",
+ "👩🏿💻",
+ "👩🏿💼",
+ "👩🏿🔧",
+ "👩🏿🔬",
+ "👩🏿🚀",
+ "👩🏿🚒",
+ "👩🏿⚕️",
+ "👩🏿⚖️",
+ "👩🏿✈️",
+ "👩🏿",
+ "👩🌾",
+ "👩🍳",
+ "👩🎓",
+ "👩🎤",
+ "👩🎨",
+ "👩🏫",
+ "👩🏭",
+ "👩👦👦",
+ "👩👦",
+ "👩👧👦",
+ "👩👧👧",
+ "👩👧",
+ "👩👩👦👦",
+ "👩👩👦",
+ "👩👩👧👦",
+ "👩👩👧👧",
+ "👩👩👧",
+ "👩💻",
+ "👩💼",
+ "👩🔧",
+ "👩🔬",
+ "👩🚀",
+ "👩🚒",
+ "👩⚕️",
+ "👩⚖️",
+ "👩✈️",
+ "👩❤️👨",
+ "👩❤️👩",
+ "👩❤️💋👨",
+ "👩❤️💋👩",
+ "👩",
+ "👪🏻",
+ "👪🏼",
+ "👪🏽",
+ "👪🏾",
+ "👪🏿",
+ "👪",
+ "👫🏻",
+ "👫🏼",
+ "👫🏽",
+ "👫🏾",
+ "👫🏿",
+ "👫",
+ "👬🏻",
+ "👬🏼",
+ "👬🏽",
+ "👬🏾",
+ "👬🏿",
+ "👬",
+ "👭🏻",
+ "👭🏼",
+ "👭🏽",
+ "👭🏾",
+ "👭🏿",
+ "👭",
+ "👮🏻♀️",
+ "👮🏻♂️",
+ "👮🏻",
+ "👮🏼♀️",
+ "👮🏼♂️",
+ "👮🏼",
+ "👮🏽♀️",
+ "👮🏽♂️",
+ "👮🏽",
+ "👮🏾♀️",
+ "👮🏾♂️",
+ "👮🏾",
+ "👮🏿♀️",
+ "👮🏿♂️",
+ "👮🏿",
+ "👮♀️",
+ "👮♂️",
+ "👮",
+ "👯🏻♀️",
+ "👯🏻♂️",
+ "👯🏻",
+ "👯🏼♀️",
+ "👯🏼♂️",
+ "👯🏼",
+ "👯🏽♀️",
+ "👯🏽♂️",
+ "👯🏽",
+ "👯🏾♀️",
+ "👯🏾♂️",
+ "👯🏾",
+ "👯🏿♀️",
+ "👯🏿♂️",
+ "👯🏿",
+ "👯♀️",
+ "👯♂️",
+ "👯",
+ "👰🏻",
+ "👰🏼",
+ "👰🏽",
+ "👰🏾",
+ "👰🏿",
+ "👰",
+ "👱🏻♀️",
+ "👱🏻♂️",
+ "👱🏻",
+ "👱🏼♀️",
+ "👱🏼♂️",
+ "👱🏼",
+ "👱🏽♀️",
+ "👱🏽♂️",
+ "👱🏽",
+ "👱🏾♀️",
+ "👱🏾♂️",
+ "👱🏾",
+ "👱🏿♀️",
+ "👱🏿♂️",
+ "👱🏿",
+ "👱♀️",
+ "👱♂️",
+ "👱",
+ "👲🏻",
+ "👲🏼",
+ "👲🏽",
+ "👲🏾",
+ "👲🏿",
+ "👲",
+ "👳🏻♀️",
+ "👳🏻♂️",
+ "👳🏻",
+ "👳🏼♀️",
+ "👳🏼♂️",
+ "👳🏼",
+ "👳🏽♀️",
+ "👳🏽♂️",
+ "👳🏽",
+ "👳🏾♀️",
+ "👳🏾♂️",
+ "👳🏾",
+ "👳🏿♀️",
+ "👳🏿♂️",
+ "👳🏿",
+ "👳♀️",
+ "👳♂️",
+ "👳",
+ "👴🏻",
+ "👴🏼",
+ "👴🏽",
+ "👴🏾",
+ "👴🏿",
+ "👴",
+ "👵🏻",
+ "👵🏼",
+ "👵🏽",
+ "👵🏾",
+ "👵🏿",
+ "👵",
+ "👶🏻",
+ "👶🏼",
+ "👶🏽",
+ "👶🏾",
+ "👶🏿",
+ "👶",
+ "👷🏻♀️",
+ "👷🏻♂️",
+ "👷🏻",
+ "👷🏼♀️",
+ "👷🏼♂️",
+ "👷🏼",
+ "👷🏽♀️",
+ "👷🏽♂️",
+ "👷🏽",
+ "👷🏾♀️",
+ "👷🏾♂️",
+ "👷🏾",
+ "👷🏿♀️",
+ "👷🏿♂️",
+ "👷🏿",
+ "👷♀️",
+ "👷♂️",
+ "👷",
+ "👸🏻",
+ "👸🏼",
+ "👸🏽",
+ "👸🏾",
+ "👸🏿",
+ "👸",
+ "👹",
+ "👺",
+ "👻",
+ "👼🏻",
+ "👼🏼",
+ "👼🏽",
+ "👼🏾",
+ "👼🏿",
+ "👼",
+ "👽",
+ "👾",
+ "👿",
+ "💀",
+ "💁🏻♀️",
+ "💁🏻♂️",
+ "💁🏻",
+ "💁🏼♀️",
+ "💁🏼♂️",
+ "💁🏼",
+ "💁🏽♀️",
+ "💁🏽♂️",
+ "💁🏽",
+ "💁🏾♀️",
+ "💁🏾♂️",
+ "💁🏾",
+ "💁🏿♀️",
+ "💁🏿♂️",
+ "💁🏿",
+ "💁♀️",
+ "💁♂️",
+ "💁",
+ "💂🏻♀️",
+ "💂🏻♂️",
+ "💂🏻",
+ "💂🏼♀️",
+ "💂🏼♂️",
+ "💂🏼",
+ "💂🏽♀️",
+ "💂🏽♂️",
+ "💂🏽",
+ "💂🏾♀️",
+ "💂🏾♂️",
+ "💂🏾",
+ "💂🏿♀️",
+ "💂🏿♂️",
+ "💂🏿",
+ "💂♀️",
+ "💂♂️",
+ "💂",
+ "💃🏻",
+ "💃🏼",
+ "💃🏽",
+ "💃🏾",
+ "💃🏿",
+ "💃",
+ "💄",
+ "💅🏻",
+ "💅🏼",
+ "💅🏽",
+ "💅🏾",
+ "💅🏿",
+ "💅",
+ "💆🏻♀️",
+ "💆🏻♂️",
+ "💆🏻",
+ "💆🏼♀️",
+ "💆🏼♂️",
+ "💆🏼",
+ "💆🏽♀️",
+ "💆🏽♂️",
+ "💆🏽",
+ "💆🏾♀️",
+ "💆🏾♂️",
+ "💆🏾",
+ "💆🏿♀️",
+ "💆🏿♂️",
+ "💆🏿",
+ "💆♀️",
+ "💆♂️",
+ "💆",
+ "💇🏻♀️",
+ "💇🏻♂️",
+ "💇🏻",
+ "💇🏼♀️",
+ "💇🏼♂️",
+ "💇🏼",
+ "💇🏽♀️",
+ "💇🏽♂️",
+ "💇🏽",
+ "💇🏾♀️",
+ "💇🏾♂️",
+ "💇🏾",
+ "💇🏿♀️",
+ "💇🏿♂️",
+ "💇🏿",
+ "💇♀️",
+ "💇♂️",
+ "💇",
+ "💈",
+ "💉",
+ "💊",
+ "💋",
+ "💌",
+ "💍",
+ "💎",
+ "💏",
+ "💐",
+ "💑",
+ "💒",
+ "💓",
+ "💔",
+ "💕",
+ "💖",
+ "💗",
+ "💘",
+ "💙",
+ "💚",
+ "💛",
+ "💜",
+ "💝",
+ "💞",
+ "💟",
+ "💠",
+ "💡",
+ "💢",
+ "💣",
+ "💤",
+ "💥",
+ "💦",
+ "💧",
+ "💨",
+ "💩",
+ "💪🏻",
+ "💪🏼",
+ "💪🏽",
+ "💪🏾",
+ "💪🏿",
+ "💪",
+ "💫",
+ "💬",
+ "💭",
+ "💮",
+ "💯",
+ "💰",
+ "💱",
+ "💲",
+ "💳",
+ "💴",
+ "💵",
+ "💶",
+ "💷",
+ "💸",
+ "💹",
+ "💺",
+ "💻",
+ "💼",
+ "💽",
+ "💾",
+ "💿",
+ "📀",
+ "📁",
+ "📂",
+ "📃",
+ "📄",
+ "📅",
+ "📆",
+ "📇",
+ "📈",
+ "📉",
+ "📊",
+ "📋",
+ "📌",
+ "📍",
+ "📎",
+ "📏",
+ "📐",
+ "📑",
+ "📒",
+ "📓",
+ "📔",
+ "📕",
+ "📖",
+ "📗",
+ "📘",
+ "📙",
+ "📚",
+ "📛",
+ "📜",
+ "📝",
+ "📞",
+ "📟",
+ "📠",
+ "📡",
+ "📢",
+ "📣",
+ "📤",
+ "📥",
+ "📦",
+ "📧",
+ "📨",
+ "📩",
+ "📪",
+ "📫",
+ "📬",
+ "📭",
+ "📮",
+ "📯",
+ "📰",
+ "📱",
+ "📲",
+ "📳",
+ "📴",
+ "📵",
+ "📶",
+ "📷",
+ "📸",
+ "📹",
+ "📺",
+ "📻",
+ "📼",
+ "📽",
+ "📿",
+ "🔀",
+ "🔁",
+ "🔂",
+ "🔃",
+ "🔄",
+ "🔅",
+ "🔆",
+ "🔇",
+ "🔈",
+ "🔉",
+ "🔊",
+ "🔋",
+ "🔌",
+ "🔍",
+ "🔎",
+ "🔏",
+ "🔐",
+ "🔑",
+ "🔒",
+ "🔓",
+ "🔔",
+ "🔕",
+ "🔖",
+ "🔗",
+ "🔘",
+ "🔙",
+ "🔚",
+ "🔛",
+ "🔜",
+ "🔝",
+ "🔞",
+ "🔟",
+ "🔠",
+ "🔡",
+ "🔢",
+ "🔣",
+ "🔤",
+ "🔥",
+ "🔦",
+ "🔧",
+ "🔨",
+ "🔩",
+ "🔪",
+ "🔫",
+ "🔬",
+ "🔭",
+ "🔮",
+ "🔯",
+ "🔰",
+ "🔱",
+ "🔲",
+ "🔳",
+ "🔴",
+ "🔵",
+ "🔶",
+ "🔷",
+ "🔸",
+ "🔹",
+ "🔺",
+ "🔻",
+ "🔼",
+ "🔽",
+ "🕉",
+ "🕊",
+ "🕋",
+ "🕌",
+ "🕍",
+ "🕎",
+ "🕐",
+ "🕑",
+ "🕒",
+ "🕓",
+ "🕔",
+ "🕕",
+ "🕖",
+ "🕗",
+ "🕘",
+ "🕙",
+ "🕚",
+ "🕛",
+ "🕜",
+ "🕝",
+ "🕞",
+ "🕟",
+ "🕠",
+ "🕡",
+ "🕢",
+ "🕣",
+ "🕤",
+ "🕥",
+ "🕦",
+ "🕧",
+ "🕯",
+ "🕰",
+ "🕳",
+ "🕴🏻",
+ "🕴🏼",
+ "🕴🏽",
+ "🕴🏾",
+ "🕴🏿",
+ "🕴",
+ "🕵🏻♀️",
+ "🕵🏻♂️",
+ "🕵🏻",
+ "🕵🏼♀️",
+ "🕵🏼♂️",
+ "🕵🏼",
+ "🕵🏽♀️",
+ "🕵🏽♂️",
+ "🕵🏽",
+ "🕵🏾♀️",
+ "🕵🏾♂️",
+ "🕵🏾",
+ "🕵🏿♀️",
+ "🕵🏿♂️",
+ "🕵🏿",
+ "🕵️♀️",
+ "🕵️♂️",
+ "🕵",
+ "🕶",
+ "🕷",
+ "🕸",
+ "🕹",
+ "🕺🏻",
+ "🕺🏼",
+ "🕺🏽",
+ "🕺🏾",
+ "🕺🏿",
+ "🕺",
+ "🖇",
+ "🖊",
+ "🖋",
+ "🖌",
+ "🖍",
+ "🖐🏻",
+ "🖐🏼",
+ "🖐🏽",
+ "🖐🏾",
+ "🖐🏿",
+ "🖐",
+ "🖕🏻",
+ "🖕🏼",
+ "🖕🏽",
+ "🖕🏾",
+ "🖕🏿",
+ "🖕",
+ "🖖🏻",
+ "🖖🏼",
+ "🖖🏽",
+ "🖖🏾",
+ "🖖🏿",
+ "🖖",
+ "🖤",
+ "🖥",
+ "🖨",
+ "🖱",
+ "🖲",
+ "🖼",
+ "🗂",
+ "🗃",
+ "🗄",
+ "🗑",
+ "🗒",
+ "🗓",
+ "🗜",
+ "🗝",
+ "🗞",
+ "🗡",
+ "🗣",
+ "🗨",
+ "🗯",
+ "🗳",
+ "🗺",
+ "🗻",
+ "🗼",
+ "🗽",
+ "🗾",
+ "🗿",
+ "😀",
+ "😁",
+ "😂",
+ "😃",
+ "😄",
+ "😅",
+ "😆",
+ "😇",
+ "😈",
+ "😉",
+ "😊",
+ "😋",
+ "😌",
+ "😍",
+ "😎",
+ "😏",
+ "😐",
+ "😑",
+ "😒",
+ "😓",
+ "😔",
+ "😕",
+ "😖",
+ "😗",
+ "😘",
+ "😙",
+ "😚",
+ "😛",
+ "😜",
+ "😝",
+ "😞",
+ "😟",
+ "😠",
+ "😡",
+ "😢",
+ "😣",
+ "😤",
+ "😥",
+ "😦",
+ "😧",
+ "😨",
+ "😩",
+ "😪",
+ "😫",
+ "😬",
+ "😭",
+ "😮",
+ "😯",
+ "😰",
+ "😱",
+ "😲",
+ "😳",
+ "😴",
+ "😵",
+ "😶",
+ "😷",
+ "😸",
+ "😹",
+ "😺",
+ "😻",
+ "😼",
+ "😽",
+ "😾",
+ "😿",
+ "🙀",
+ "🙁",
+ "🙂",
+ "🙃",
+ "🙄",
+ "🙅🏻♀️",
+ "🙅🏻♂️",
+ "🙅🏻",
+ "🙅🏼♀️",
+ "🙅🏼♂️",
+ "🙅🏼",
+ "🙅🏽♀️",
+ "🙅🏽♂️",
+ "🙅🏽",
+ "🙅🏾♀️",
+ "🙅🏾♂️",
+ "🙅🏾",
+ "🙅🏿♀️",
+ "🙅🏿♂️",
+ "🙅🏿",
+ "🙅♀️",
+ "🙅♂️",
+ "🙅",
+ "🙆🏻♀️",
+ "🙆🏻♂️",
+ "🙆🏻",
+ "🙆🏼♀️",
+ "🙆🏼♂️",
+ "🙆🏼",
+ "🙆🏽♀️",
+ "🙆🏽♂️",
+ "🙆🏽",
+ "🙆🏾♀️",
+ "🙆🏾♂️",
+ "🙆🏾",
+ "🙆🏿♀️",
+ "🙆🏿♂️",
+ "🙆🏿",
+ "🙆♀️",
+ "🙆♂️",
+ "🙆",
+ "🙇🏻♀️",
+ "🙇🏻♂️",
+ "🙇🏻",
+ "🙇🏼♀️",
+ "🙇🏼♂️",
+ "🙇🏼",
+ "🙇🏽♀️",
+ "🙇🏽♂️",
+ "🙇🏽",
+ "🙇🏾♀️",
+ "🙇🏾♂️",
+ "🙇🏾",
+ "🙇🏿♀️",
+ "🙇🏿♂️",
+ "🙇🏿",
+ "🙇♀️",
+ "🙇♂️",
+ "🙇",
+ "🙈",
+ "🙉",
+ "🙊",
+ "🙋🏻♀️",
+ "🙋🏻♂️",
+ "🙋🏻",
+ "🙋🏼♀️",
+ "🙋🏼♂️",
+ "🙋🏼",
+ "🙋🏽♀️",
+ "🙋🏽♂️",
+ "🙋🏽",
+ "🙋🏾♀️",
+ "🙋🏾♂️",
+ "🙋🏾",
+ "🙋🏿♀️",
+ "🙋🏿♂️",
+ "🙋🏿",
+ "🙋♀️",
+ "🙋♂️",
+ "🙋",
+ "🙌🏻",
+ "🙌🏼",
+ "🙌🏽",
+ "🙌🏾",
+ "🙌🏿",
+ "🙌",
+ "🙍🏻♀️",
+ "🙍🏻♂️",
+ "🙍🏻",
+ "🙍🏼♀️",
+ "🙍🏼♂️",
+ "🙍🏼",
+ "🙍🏽♀️",
+ "🙍🏽♂️",
+ "🙍🏽",
+ "🙍🏾♀️",
+ "🙍🏾♂️",
+ "🙍🏾",
+ "🙍🏿♀️",
+ "🙍🏿♂️",
+ "🙍🏿",
+ "🙍♀️",
+ "🙍♂️",
+ "🙍",
+ "🙎🏻♀️",
+ "🙎🏻♂️",
+ "🙎🏻",
+ "🙎🏼♀️",
+ "🙎🏼♂️",
+ "🙎🏼",
+ "🙎🏽♀️",
+ "🙎🏽♂️",
+ "🙎🏽",
+ "🙎🏾♀️",
+ "🙎🏾♂️",
+ "🙎🏾",
+ "🙎🏿♀️",
+ "🙎🏿♂️",
+ "🙎🏿",
+ "🙎♀️",
+ "🙎♂️",
+ "🙎",
+ "🙏🏻",
+ "🙏🏼",
+ "🙏🏽",
+ "🙏🏾",
+ "🙏🏿",
+ "🙏",
+ "🚀",
+ "🚁",
+ "🚂",
+ "🚃",
+ "🚄",
+ "🚅",
+ "🚆",
+ "🚇",
+ "🚈",
+ "🚉",
+ "🚊",
+ "🚋",
+ "🚌",
+ "🚍",
+ "🚎",
+ "🚏",
+ "🚐",
+ "🚑",
+ "🚒",
+ "🚓",
+ "🚔",
+ "🚕",
+ "🚖",
+ "🚗",
+ "🚘",
+ "🚙",
+ "🚚",
+ "🚛",
+ "🚜",
+ "🚝",
+ "🚞",
+ "🚟",
+ "🚠",
+ "🚡",
+ "🚢",
+ "🚣🏻♀️",
+ "🚣🏻♂️",
+ "🚣🏻",
+ "🚣🏼♀️",
+ "🚣🏼♂️",
+ "🚣🏼",
+ "🚣🏽♀️",
+ "🚣🏽♂️",
+ "🚣🏽",
+ "🚣🏾♀️",
+ "🚣🏾♂️",
+ "🚣🏾",
+ "🚣🏿♀️",
+ "🚣🏿♂️",
+ "🚣🏿",
+ "🚣♀️",
+ "🚣♂️",
+ "🚣",
+ "🚤",
+ "🚥",
+ "🚦",
+ "🚧",
+ "🚨",
+ "🚩",
+ "🚪",
+ "🚫",
+ "🚬",
+ "🚭",
+ "🚮",
+ "🚯",
+ "🚰",
+ "🚱",
+ "🚲",
+ "🚳",
+ "🚴🏻♀️",
+ "🚴🏻♂️",
+ "🚴🏻",
+ "🚴🏼♀️",
+ "🚴🏼♂️",
+ "🚴🏼",
+ "🚴🏽♀️",
+ "🚴🏽♂️",
+ "🚴🏽",
+ "🚴🏾♀️",
+ "🚴🏾♂️",
+ "🚴🏾",
+ "🚴🏿♀️",
+ "🚴🏿♂️",
+ "🚴🏿",
+ "🚴♀️",
+ "🚴♂️",
+ "🚴",
+ "🚵🏻♀️",
+ "🚵🏻♂️",
+ "🚵🏻",
+ "🚵🏼♀️",
+ "🚵🏼♂️",
+ "🚵🏼",
+ "🚵🏽♀️",
+ "🚵🏽♂️",
+ "🚵🏽",
+ "🚵🏾♀️",
+ "🚵🏾♂️",
+ "🚵🏾",
+ "🚵🏿♀️",
+ "🚵🏿♂️",
+ "🚵🏿",
+ "🚵♀️",
+ "🚵♂️",
+ "🚵",
+ "🚶🏻♀️",
+ "🚶🏻♂️",
+ "🚶🏻",
+ "🚶🏼♀️",
+ "🚶🏼♂️",
+ "🚶🏼",
+ "🚶🏽♀️",
+ "🚶🏽♂️",
+ "🚶🏽",
+ "🚶🏾♀️",
+ "🚶🏾♂️",
+ "🚶🏾",
+ "🚶🏿♀️",
+ "🚶🏿♂️",
+ "🚶🏿",
+ "🚶♀️",
+ "🚶♂️",
+ "🚶",
+ "🚷",
+ "🚸",
+ "🚹",
+ "🚺",
+ "🚻",
+ "🚼",
+ "🚽",
+ "🚾",
+ "🚿",
+ "🛀🏻",
+ "🛀🏼",
+ "🛀🏽",
+ "🛀🏾",
+ "🛀🏿",
+ "🛀",
+ "🛁",
+ "🛂",
+ "🛃",
+ "🛄",
+ "🛅",
+ "🛋",
+ "🛌🏻",
+ "🛌🏼",
+ "🛌🏽",
+ "🛌🏾",
+ "🛌🏿",
+ "🛌",
+ "🛍",
+ "🛎",
+ "🛏",
+ "🛐",
+ "🛑",
+ "🛒",
+ "🛠",
+ "🛡",
+ "🛢",
+ "🛣",
+ "🛤",
+ "🛥",
+ "🛩",
+ "🛫",
+ "🛬",
+ "🛰",
+ "🛳",
+ "🛴",
+ "🛵",
+ "🛶",
+ "🤐",
+ "🤑",
+ "🤒",
+ "🤓",
+ "🤔",
+ "🤕",
+ "🤖",
+ "🤗",
+ "🤘🏻",
+ "🤘🏼",
+ "🤘🏽",
+ "🤘🏾",
+ "🤘🏿",
+ "🤘",
+ "🤙🏻",
+ "🤙🏼",
+ "🤙🏽",
+ "🤙🏾",
+ "🤙🏿",
+ "🤙",
+ "🤚🏻",
+ "🤚🏼",
+ "🤚🏽",
+ "🤚🏾",
+ "🤚🏿",
+ "🤚",
+ "🤛🏻",
+ "🤛🏼",
+ "🤛🏽",
+ "🤛🏾",
+ "🤛🏿",
+ "🤛",
+ "🤜🏻",
+ "🤜🏼",
+ "🤜🏽",
+ "🤜🏾",
+ "🤜🏿",
+ "🤜",
+ "🤝🏻",
+ "🤝🏼",
+ "🤝🏽",
+ "🤝🏾",
+ "🤝🏿",
+ "🤝",
+ "🤞🏻",
+ "🤞🏼",
+ "🤞🏽",
+ "🤞🏾",
+ "🤞🏿",
+ "🤞",
+ "🤠",
+ "🤡",
+ "🤢",
+ "🤣",
+ "🤤",
+ "🤥",
+ "🤦🏻♀️",
+ "🤦🏻♂️",
+ "🤦🏻",
+ "🤦🏼♀️",
+ "🤦🏼♂️",
+ "🤦🏼",
+ "🤦🏽♀️",
+ "🤦🏽♂️",
+ "🤦🏽",
+ "🤦🏾♀️",
+ "🤦🏾♂️",
+ "🤦🏾",
+ "🤦🏿♀️",
+ "🤦🏿♂️",
+ "🤦🏿",
+ "🤦♀️",
+ "🤦♂️",
+ "🤦",
+ "🤧",
+ "🤰🏻",
+ "🤰🏼",
+ "🤰🏽",
+ "🤰🏾",
+ "🤰🏿",
+ "🤰",
+ "🤳🏻",
+ "🤳🏼",
+ "🤳🏽",
+ "🤳🏾",
+ "🤳🏿",
+ "🤳",
+ "🤴🏻",
+ "🤴🏼",
+ "🤴🏽",
+ "🤴🏾",
+ "🤴🏿",
+ "🤴",
+ "🤵🏻",
+ "🤵🏼",
+ "🤵🏽",
+ "🤵🏾",
+ "🤵🏿",
+ "🤵",
+ "🤶🏻",
+ "🤶🏼",
+ "🤶🏽",
+ "🤶🏾",
+ "🤶🏿",
+ "🤶",
+ "🤷🏻♀️",
+ "🤷🏻♂️",
+ "🤷🏻",
+ "🤷🏼♀️",
+ "🤷🏼♂️",
+ "🤷🏼",
+ "🤷🏽♀️",
+ "🤷🏽♂️",
+ "🤷🏽",
+ "🤷🏾♀️",
+ "🤷🏾♂️",
+ "🤷🏾",
+ "🤷🏿♀️",
+ "🤷🏿♂️",
+ "🤷🏿",
+ "🤷♀️",
+ "🤷♂️",
+ "🤷",
+ "🤸🏻♀️",
+ "🤸🏻♂️",
+ "🤸🏻",
+ "🤸🏼♀️",
+ "🤸🏼♂️",
+ "🤸🏼",
+ "🤸🏽♀️",
+ "🤸🏽♂️",
+ "🤸🏽",
+ "🤸🏾♀️",
+ "🤸🏾♂️",
+ "🤸🏾",
+ "🤸🏿♀️",
+ "🤸🏿♂️",
+ "🤸🏿",
+ "🤸♀️",
+ "🤸♂️",
+ "🤸",
+ "🤹🏻♀️",
+ "🤹🏻♂️",
+ "🤹🏻",
+ "🤹🏼♀️",
+ "🤹🏼♂️",
+ "🤹🏼",
+ "🤹🏽♀️",
+ "🤹🏽♂️",
+ "🤹🏽",
+ "🤹🏾♀️",
+ "🤹🏾♂️",
+ "🤹🏾",
+ "🤹🏿♀️",
+ "🤹🏿♂️",
+ "🤹🏿",
+ "🤹♀️",
+ "🤹♂️",
+ "🤹",
+ "🤺",
+ "🤼🏻♀️",
+ "🤼🏻♂️",
+ "🤼🏻",
+ "🤼🏼♀️",
+ "🤼🏼♂️",
+ "🤼🏼",
+ "🤼🏽♀️",
+ "🤼🏽♂️",
+ "🤼🏽",
+ "🤼🏾♀️",
+ "🤼🏾♂️",
+ "🤼🏾",
+ "🤼🏿♀️",
+ "🤼🏿♂️",
+ "🤼🏿",
+ "🤼♀️",
+ "🤼♂️",
+ "🤼",
+ "🤽🏻♀️",
+ "🤽🏻♂️",
+ "🤽🏻",
+ "🤽🏼♀️",
+ "🤽🏼♂️",
+ "🤽🏼",
+ "🤽🏽♀️",
+ "🤽🏽♂️",
+ "🤽🏽",
+ "🤽🏾♀️",
+ "🤽🏾♂️",
+ "🤽🏾",
+ "🤽🏿♀️",
+ "🤽🏿♂️",
+ "🤽🏿",
+ "🤽♀️",
+ "🤽♂️",
+ "🤽",
+ "🤾🏻♀️",
+ "🤾🏻♂️",
+ "🤾🏻",
+ "🤾🏼♀️",
+ "🤾🏼♂️",
+ "🤾🏼",
+ "🤾🏽♀️",
+ "🤾🏽♂️",
+ "🤾🏽",
+ "🤾🏾♀️",
+ "🤾🏾♂️",
+ "🤾🏾",
+ "🤾🏿♀️",
+ "🤾🏿♂️",
+ "🤾🏿",
+ "🤾♀️",
+ "🤾♂️",
+ "🤾",
+ "🥀",
+ "🥁",
+ "🥂",
+ "🥃",
+ "🥄",
+ "🥅",
+ "🥇",
+ "🥈",
+ "🥉",
+ "🥊",
+ "🥋",
+ "🥐",
+ "🥑",
+ "🥒",
+ "🥓",
+ "🥔",
+ "🥕",
+ "🥖",
+ "🥗",
+ "🥘",
+ "🥙",
+ "🥚",
+ "🥛",
+ "🥜",
+ "🥝",
+ "🥞",
+ "🦀",
+ "🦁",
+ "🦂",
+ "🦃",
+ "🦄",
+ "🦅",
+ "🦆",
+ "🦇",
+ "🦈",
+ "🦉",
+ "🦊",
+ "🦋",
+ "🦌",
+ "🦍",
+ "🦎",
+ "🦏",
+ "🦐",
+ "🦑",
+ "🧀",
+ "‼",
+ "⁉",
+ "™",
+ "ℹ",
+ "↔",
+ "↕",
+ "↖",
+ "↗",
+ "↘",
+ "↙",
+ "↩",
+ "↪",
+ "#⃣",
+ "⌚",
+ "⌛",
+ "⌨",
+ "⏏",
+ "⏩",
+ "⏪",
+ "⏫",
+ "⏬",
+ "⏭",
+ "⏮",
+ "⏯",
+ "⏰",
+ "⏱",
+ "⏲",
+ "⏳",
+ "⏸",
+ "⏹",
+ "⏺",
+ "Ⓜ",
+ "▪",
+ "▫",
+ "▶",
+ "◀",
+ "◻",
+ "◼",
+ "◽",
+ "◾",
+ "☀",
+ "☁",
+ "☂",
+ "☃",
+ "☄",
+ "☎",
+ "☑",
+ "☔",
+ "☕",
+ "☘",
+ "☝🏻",
+ "☝🏼",
+ "☝🏽",
+ "☝🏾",
+ "☝🏿",
+ "☝",
+ "☠",
+ "☢",
+ "☣",
+ "☦",
+ "☪",
+ "☮",
+ "☯",
+ "☸",
+ "☹",
+ "☺",
+ "♀",
+ "♂",
+ "♈",
+ "♉",
+ "♊",
+ "♋",
+ "♌",
+ "♍",
+ "♎",
+ "♏",
+ "♐",
+ "♑",
+ "♒",
+ "♓",
+ "♠",
+ "♣",
+ "♥",
+ "♦",
+ "♨",
+ "♻",
+ "♿",
+ "⚒",
+ "⚓",
+ "⚔",
+ "⚕",
+ "⚖",
+ "⚗",
+ "⚙",
+ "⚛",
+ "⚜",
+ "⚠",
+ "⚡",
+ "⚪",
+ "⚫",
+ "⚰",
+ "⚱",
+ "⚽",
+ "⚾",
+ "⛄",
+ "⛅",
+ "⛈",
+ "⛎",
+ "⛏",
+ "⛑",
+ "⛓",
+ "⛔",
+ "⛩",
+ "⛪",
+ "⛰",
+ "⛱",
+ "⛲",
+ "⛳",
+ "⛴",
+ "⛵",
+ "⛷🏻",
+ "⛷🏼",
+ "⛷🏽",
+ "⛷🏾",
+ "⛷🏿",
+ "⛷",
+ "⛸",
+ "⛹🏻♀️",
+ "⛹🏻♂️",
+ "⛹🏻",
+ "⛹🏼♀️",
+ "⛹🏼♂️",
+ "⛹🏼",
+ "⛹🏽♀️",
+ "⛹🏽♂️",
+ "⛹🏽",
+ "⛹🏾♀️",
+ "⛹🏾♂️",
+ "⛹🏾",
+ "⛹🏿♀️",
+ "⛹🏿♂️",
+ "⛹🏿",
+ "⛹️♀️",
+ "⛹️♂️",
+ "⛹",
+ "⛺",
+ "⛽",
+ "✂",
+ "✅",
+ "✈",
+ "✉",
+ "✊🏻",
+ "✊🏼",
+ "✊🏽",
+ "✊🏾",
+ "✊🏿",
+ "✊",
+ "✋🏻",
+ "✋🏼",
+ "✋🏽",
+ "✋🏾",
+ "✋🏿",
+ "✋",
+ "✌🏻",
+ "✌🏼",
+ "✌🏽",
+ "✌🏾",
+ "✌🏿",
+ "✌",
+ "✍🏻",
+ "✍🏼",
+ "✍🏽",
+ "✍🏾",
+ "✍🏿",
+ "✍",
+ "✏",
+ "✒",
+ "✔",
+ "✖",
+ "✝",
+ "✡",
+ "✨",
+ "✳",
+ "✴",
+ "❄",
+ "❇",
+ "❌",
+ "❎",
+ "❓",
+ "❔",
+ "❕",
+ "❗",
+ "❣",
+ "❤",
+ "➕",
+ "➖",
+ "➗",
+ "➡",
+ "➰",
+ "➿",
+ "⤴",
+ "⤵",
+ "*⃣",
+ "⬅",
+ "⬆",
+ "⬇",
+ "⬛",
+ "⬜",
+ "⭐",
+ "⭕",
+ "0⃣",
+ "〰",
+ "〽",
+ "1⃣",
+ "2⃣",
+ "㊗",
+ "㊙",
+ "3⃣",
+ "4⃣",
+ "5⃣",
+ "6⃣",
+ "7⃣",
+ "8⃣",
+ "9⃣",
+ "©",
+ "®",
+ ""
+];
+
+frappe.ui.emoji_keywords = [
+ ":mahjong:",
+ ":black_joker:",
+ ":a:",
+ ":b:",
+ ":o2:",
+ ":parking:",
+ ":ab:",
+ ":cl:",
+ ":cool:",
+ ":free:",
+ ":id:",
+ ":new:",
+ ":ng:",
+ ":ok:",
+ ":sos:",
+ ":up:",
+ ":vs:",
+ ":flag_ac:",
+ ":flag_ad:",
+ ":flag_ae:",
+ ":flag_af:",
+ ":flag_ag:",
+ ":flag_ai:",
+ ":flag_al:",
+ ":flag_am:",
+ ":flag_ao:",
+ ":flag_aq:",
+ ":flag_ar:",
+ ":flag_as:",
+ ":flag_at:",
+ ":flag_au:",
+ ":flag_aw:",
+ ":flag_ax:",
+ ":flag_az:",
+ ":regional_indicator_a:",
+ ":flag_ba:",
+ ":flag_bb:",
+ ":flag_bd:",
+ ":flag_be:",
+ ":flag_bf:",
+ ":flag_bg:",
+ ":flag_bh:",
+ ":flag_bi:",
+ ":flag_bj:",
+ ":flag_bl:",
+ ":flag_bm:",
+ ":flag_bn:",
+ ":flag_bo:",
+ ":flag_bq:",
+ ":flag_br:",
+ ":flag_bs:",
+ ":flag_bt:",
+ ":flag_bv:",
+ ":flag_bw:",
+ ":flag_by:",
+ ":flag_bz:",
+ ":regional_indicator_b:",
+ ":flag_ca:",
+ ":flag_cc:",
+ ":flag_cd:",
+ ":flag_cf:",
+ ":flag_cg:",
+ ":flag_ch:",
+ ":flag_ci:",
+ ":flag_ck:",
+ ":flag_cl:",
+ ":flag_cm:",
+ ":flag_cn:",
+ ":flag_co:",
+ ":flag_cp:",
+ ":flag_cr:",
+ ":flag_cu:",
+ ":flag_cv:",
+ ":flag_cw:",
+ ":flag_cx:",
+ ":flag_cy:",
+ ":flag_cz:",
+ ":regional_indicator_c:",
+ ":flag_de:",
+ ":flag_dg:",
+ ":flag_dj:",
+ ":flag_dk:",
+ ":flag_dm:",
+ ":flag_do:",
+ ":flag_dz:",
+ ":regional_indicator_d:",
+ ":flag_ea:",
+ ":flag_ec:",
+ ":flag_ee:",
+ ":flag_eg:",
+ ":flag_eh:",
+ ":flag_er:",
+ ":flag_es:",
+ ":flag_et:",
+ ":flag_eu:",
+ ":regional_indicator_e:",
+ ":flag_fi:",
+ ":flag_fj:",
+ ":flag_fk:",
+ ":flag_fm:",
+ ":flag_fo:",
+ ":flag_fr:",
+ ":regional_indicator_f:",
+ ":flag_ga:",
+ ":flag_gb:",
+ ":flag_gd:",
+ ":flag_ge:",
+ ":flag_gf:",
+ ":flag_gg:",
+ ":flag_gh:",
+ ":flag_gi:",
+ ":flag_gl:",
+ ":flag_gm:",
+ ":flag_gn:",
+ ":flag_gp:",
+ ":flag_gq:",
+ ":flag_gr:",
+ ":flag_gs:",
+ ":flag_gt:",
+ ":flag_gu:",
+ ":flag_gw:",
+ ":flag_gy:",
+ ":regional_indicator_g:",
+ ":flag_hk:",
+ ":flag_hm:",
+ ":flag_hn:",
+ ":flag_hr:",
+ ":flag_ht:",
+ ":flag_hu:",
+ ":regional_indicator_h:",
+ ":flag_ic:",
+ ":flag_id:",
+ ":flag_ie:",
+ ":flag_il:",
+ ":flag_im:",
+ ":flag_in:",
+ ":flag_io:",
+ ":flag_iq:",
+ ":flag_ir:",
+ ":flag_is:",
+ ":flag_it:",
+ ":regional_indicator_i:",
+ ":flag_je:",
+ ":flag_jm:",
+ ":flag_jo:",
+ ":flag_jp:",
+ ":regional_indicator_j:",
+ ":flag_ke:",
+ ":flag_kg:",
+ ":flag_kh:",
+ ":flag_ki:",
+ ":flag_km:",
+ ":flag_kn:",
+ ":flag_kp:",
+ ":flag_kr:",
+ ":flag_kw:",
+ ":flag_ky:",
+ ":flag_kz:",
+ ":regional_indicator_k:",
+ ":flag_la:",
+ ":flag_lb:",
+ ":flag_lc:",
+ ":flag_li:",
+ ":flag_lk:",
+ ":flag_lr:",
+ ":flag_ls:",
+ ":flag_lt:",
+ ":flag_lu:",
+ ":flag_lv:",
+ ":flag_ly:",
+ ":regional_indicator_l:",
+ ":flag_ma:",
+ ":flag_mc:",
+ ":flag_md:",
+ ":flag_me:",
+ ":flag_mf:",
+ ":flag_mg:",
+ ":flag_mh:",
+ ":flag_mk:",
+ ":flag_ml:",
+ ":flag_mm:",
+ ":flag_mn:",
+ ":flag_mo:",
+ ":flag_mp:",
+ ":flag_mq:",
+ ":flag_mr:",
+ ":flag_ms:",
+ ":flag_mt:",
+ ":flag_mu:",
+ ":flag_mv:",
+ ":flag_mw:",
+ ":flag_mx:",
+ ":flag_my:",
+ ":flag_mz:",
+ ":regional_indicator_m:",
+ ":flag_na:",
+ ":flag_nc:",
+ ":flag_ne:",
+ ":flag_nf:",
+ ":flag_ng:",
+ ":flag_ni:",
+ ":flag_nl:",
+ ":flag_no:",
+ ":flag_np:",
+ ":flag_nr:",
+ ":flag_nu:",
+ ":flag_nz:",
+ ":regional_indicator_n:",
+ ":flag_om:",
+ ":regional_indicator_o:",
+ ":flag_pa:",
+ ":flag_pe:",
+ ":flag_pf:",
+ ":flag_pg:",
+ ":flag_ph:",
+ ":flag_pk:",
+ ":flag_pl:",
+ ":flag_pm:",
+ ":flag_pn:",
+ ":flag_pr:",
+ ":flag_ps:",
+ ":flag_pt:",
+ ":flag_pw:",
+ ":flag_py:",
+ ":regional_indicator_p:",
+ ":flag_qa:",
+ ":regional_indicator_q:",
+ ":flag_re:",
+ ":flag_ro:",
+ ":flag_rs:",
+ ":flag_ru:",
+ ":flag_rw:",
+ ":regional_indicator_r:",
+ ":flag_sa:",
+ ":flag_sb:",
+ ":flag_sc:",
+ ":flag_sd:",
+ ":flag_se:",
+ ":flag_sg:",
+ ":flag_sh:",
+ ":flag_si:",
+ ":flag_sj:",
+ ":flag_sk:",
+ ":flag_sl:",
+ ":flag_sm:",
+ ":flag_sn:",
+ ":flag_so:",
+ ":flag_sr:",
+ ":flag_ss:",
+ ":flag_st:",
+ ":flag_sv:",
+ ":flag_sx:",
+ ":flag_sy:",
+ ":flag_sz:",
+ ":regional_indicator_s:",
+ ":flag_ta:",
+ ":flag_tc:",
+ ":flag_td:",
+ ":flag_tf:",
+ ":flag_tg:",
+ ":flag_th:",
+ ":flag_tj:",
+ ":flag_tk:",
+ ":flag_tl:",
+ ":flag_tm:",
+ ":flag_tn:",
+ ":flag_to:",
+ ":flag_tr:",
+ ":flag_tt:",
+ ":flag_tv:",
+ ":flag_tw:",
+ ":flag_tz:",
+ ":regional_indicator_t:",
+ ":flag_ua:",
+ ":flag_ug:",
+ ":flag_um:",
+ ":regional_indicator_u::regional_indicator_n:",
+ ":flag_us:",
+ ":flag_uy:",
+ ":flag_uz:",
+ ":regional_indicator_u:",
+ ":flag_va:",
+ ":flag_vc:",
+ ":flag_ve:",
+ ":flag_vg:",
+ ":flag_vi:",
+ ":flag_vn:",
+ ":flag_vu:",
+ ":regional_indicator_v:",
+ ":flag_wf:",
+ ":flag_ws:",
+ ":regional_indicator_w:",
+ ":flag_xk:",
+ ":regional_indicator_x:",
+ ":flag_ye:",
+ ":flag_yt:",
+ ":regional_indicator_y:",
+ ":flag_za:",
+ ":flag_zm:",
+ ":flag_zw:",
+ ":regional_indicator_z:",
+ ":koko:",
+ ":sa:",
+ ":u7121:",
+ ":u6307:",
+ ":u7981:",
+ ":u7a7a:",
+ ":u5408:",
+ ":u6e80:",
+ ":u6709:",
+ ":u6708:",
+ ":u7533:",
+ ":u5272:",
+ ":u55b6:",
+ ":ideograph_advantage:",
+ ":accept:",
+ ":cyclone:",
+ ":foggy:",
+ ":closed_umbrella:",
+ ":night_with_stars:",
+ ":sunrise_over_mountains:",
+ ":sunrise:",
+ ":city_dusk:",
+ ":city_sunset:",
+ ":rainbow:",
+ ":bridge_at_night:",
+ ":ocean:",
+ ":volcano:",
+ ":milky_way:",
+ ":earth_africa:",
+ ":earth_americas:",
+ ":earth_asia:",
+ ":globe_with_meridians:",
+ ":new_moon:",
+ ":waxing_crescent_moon:",
+ ":first_quarter_moon:",
+ ":waxing_gibbous_moon:",
+ ":full_moon:",
+ ":waning_gibbous_moon:",
+ ":last_quarter_moon:",
+ ":waning_crescent_moon:",
+ ":crescent_moon:",
+ ":new_moon_with_face:",
+ ":first_quarter_moon_with_face:",
+ ":last_quarter_moon_with_face:",
+ ":full_moon_with_face:",
+ ":sun_with_face:",
+ ":star2:",
+ ":stars:",
+ ":thermometer:",
+ ":white_sun_small_cloud:",
+ ":white_sun_cloud:",
+ ":white_sun_rain_cloud:",
+ ":cloud_rain:",
+ ":cloud_snow:",
+ ":cloud_lightning:",
+ ":cloud_tornado:",
+ ":fog:",
+ ":wind_blowing_face:",
+ ":hotdog:",
+ ":taco:",
+ ":burrito:",
+ ":chestnut:",
+ ":seedling:",
+ ":evergreen_tree:",
+ ":deciduous_tree:",
+ ":palm_tree:",
+ ":cactus:",
+ ":hot_pepper:",
+ ":tulip:",
+ ":cherry_blossom:",
+ ":rose:",
+ ":hibiscus:",
+ ":sunflower:",
+ ":blossom:",
+ ":corn:",
+ ":ear_of_rice:",
+ ":herb:",
+ ":four_leaf_clover:",
+ ":maple_leaf:",
+ ":fallen_leaf:",
+ ":leaves:",
+ ":mushroom:",
+ ":tomato:",
+ ":eggplant:",
+ ":grapes:",
+ ":melon:",
+ ":watermelon:",
+ ":tangerine:",
+ ":lemon:",
+ ":banana:",
+ ":pineapple:",
+ ":apple:",
+ ":green_apple:",
+ ":pear:",
+ ":peach:",
+ ":cherries:",
+ ":strawberry:",
+ ":hamburger:",
+ ":pizza:",
+ ":meat_on_bone:",
+ ":poultry_leg:",
+ ":rice_cracker:",
+ ":rice_ball:",
+ ":rice:",
+ ":curry:",
+ ":ramen:",
+ ":spaghetti:",
+ ":bread:",
+ ":fries:",
+ ":sweet_potato:",
+ ":dango:",
+ ":oden:",
+ ":sushi:",
+ ":fried_shrimp:",
+ ":fish_cake:",
+ ":icecream:",
+ ":shaved_ice:",
+ ":ice_cream:",
+ ":doughnut:",
+ ":cookie:",
+ ":chocolate_bar:",
+ ":candy:",
+ ":lollipop:",
+ ":custard:",
+ ":honey_pot:",
+ ":cake:",
+ ":bento:",
+ ":stew:",
+ ":cooking:",
+ ":fork_and_knife:",
+ ":tea:",
+ ":sake:",
+ ":wine_glass:",
+ ":cocktail:",
+ ":tropical_drink:",
+ ":beer:",
+ ":beers:",
+ ":baby_bottle:",
+ ":fork_knife_plate:",
+ ":champagne:",
+ ":popcorn:",
+ ":ribbon:",
+ ":gift:",
+ ":birthday:",
+ ":jack_o_lantern:",
+ ":christmas_tree:",
+ ":santa_tone1:",
+ ":santa_tone2:",
+ ":santa_tone3:",
+ ":santa_tone4:",
+ ":santa_tone5:",
+ ":santa:",
+ ":fireworks:",
+ ":sparkler:",
+ ":balloon:",
+ ":tada:",
+ ":confetti_ball:",
+ ":tanabata_tree:",
+ ":crossed_flags:",
+ ":bamboo:",
+ ":dolls:",
+ ":flags:",
+ ":wind_chime:",
+ ":rice_scene:",
+ ":school_satchel:",
+ ":mortar_board:",
+ ":military_medal:",
+ ":reminder_ribbon:",
+ ":microphone2:",
+ ":level_slider:",
+ ":control_knobs:",
+ ":film_frames:",
+ ":tickets:",
+ ":carousel_horse:",
+ ":ferris_wheel:",
+ ":roller_coaster:",
+ ":fishing_pole_and_fish:",
+ ":microphone:",
+ ":movie_camera:",
+ ":cinema:",
+ ":headphones:",
+ ":art:",
+ ":tophat:",
+ ":circus_tent:",
+ ":ticket:",
+ ":clapper:",
+ ":performing_arts:",
+ ":video_game:",
+ ":dart:",
+ ":slot_machine:",
+ ":8ball:",
+ ":game_die:",
+ ":bowling:",
+ ":flower_playing_cards:",
+ ":musical_note:",
+ ":notes:",
+ ":saxophone:",
+ ":guitar:",
+ ":musical_keyboard:",
+ ":trumpet:",
+ ":violin:",
+ ":musical_score:",
+ ":running_shirt_with_sash:",
+ ":tennis:",
+ ":ski:",
+ ":basketball:",
+ ":checkered_flag:",
+ ":snowboarder::tone1:",
+ ":snowboarder::tone2:",
+ ":snowboarder::tone3:",
+ ":snowboarder::tone4:",
+ ":snowboarder::tone5:",
+ ":snowboarder:",
+ ":runner_tone1:♀️",
+ ":runner_tone1:♂️",
+ ":runner_tone1:",
+ ":runner_tone2:♀️",
+ ":runner_tone2:♂️",
+ ":runner_tone2:",
+ ":runner_tone3:♀️",
+ ":runner_tone3:♂️",
+ ":runner_tone3:",
+ ":runner_tone4:♀️",
+ ":runner_tone4:♂️",
+ ":runner_tone4:",
+ ":runner_tone5:♀️",
+ ":runner_tone5:♂️",
+ ":runner_tone5:",
+ ":runner:♀️",
+ ":runner:♂️",
+ ":runner:",
+ ":surfer_tone1:♀️",
+ ":surfer_tone1:♂️",
+ ":surfer_tone1:",
+ ":surfer_tone2:♀️",
+ ":surfer_tone2:♂️",
+ ":surfer_tone2:",
+ ":surfer_tone3:♀️",
+ ":surfer_tone3:♂️",
+ ":surfer_tone3:",
+ ":surfer_tone4:♀️",
+ ":surfer_tone4:♂️",
+ ":surfer_tone4:",
+ ":surfer_tone5:♀️",
+ ":surfer_tone5:♂️",
+ ":surfer_tone5:",
+ ":surfer:♀️",
+ ":surfer:♂️",
+ ":surfer:",
+ ":medal:",
+ ":trophy:",
+ ":horse_racing_tone1:",
+ ":horse_racing_tone2:",
+ ":horse_racing_tone3:",
+ ":horse_racing_tone4:",
+ ":horse_racing_tone5:",
+ ":horse_racing:",
+ ":football:",
+ ":rugby_football:",
+ ":swimmer_tone1:♀️",
+ ":swimmer_tone1:♂️",
+ ":swimmer_tone1:",
+ ":swimmer_tone2:♀️",
+ ":swimmer_tone2:♂️",
+ ":swimmer_tone2:",
+ ":swimmer_tone3:♀️",
+ ":swimmer_tone3:♂️",
+ ":swimmer_tone3:",
+ ":swimmer_tone4:♀️",
+ ":swimmer_tone4:♂️",
+ ":swimmer_tone4:",
+ ":swimmer_tone5:♀️",
+ ":swimmer_tone5:♂️",
+ ":swimmer_tone5:",
+ ":swimmer:♀️",
+ ":swimmer:♂️",
+ ":swimmer:",
+ ":lifter_tone1:♀️",
+ ":lifter_tone1:♂️",
+ ":lifter_tone1:",
+ ":lifter_tone2:♀️",
+ ":lifter_tone2:♂️",
+ ":lifter_tone2:",
+ ":lifter_tone3:♀️",
+ ":lifter_tone3:♂️",
+ ":lifter_tone3:",
+ ":lifter_tone4:♀️",
+ ":lifter_tone4:♂️",
+ ":lifter_tone4:",
+ ":lifter_tone5:♀️",
+ ":lifter_tone5:♂️",
+ ":lifter_tone5:",
+ ":lifter:♀️",
+ ":lifter:♂️",
+ ":lifter:",
+ ":golfer::tone1:♀️",
+ ":golfer::tone1:♂️",
+ ":golfer::tone1:",
+ ":golfer::tone2:♀️",
+ ":golfer::tone2:♂️",
+ ":golfer::tone2:",
+ ":golfer::tone3:♀️",
+ ":golfer::tone3:♂️",
+ ":golfer::tone3:",
+ ":golfer::tone4:♀️",
+ ":golfer::tone4:♂️",
+ ":golfer::tone4:",
+ ":golfer::tone5:♀️",
+ ":golfer::tone5:♂️",
+ ":golfer::tone5:",
+ ":golfer:♀️",
+ ":golfer:♂️",
+ ":golfer:",
+ ":motorcycle:",
+ ":race_car:",
+ ":cricket:",
+ ":volleyball:",
+ ":field_hockey:",
+ ":hockey:",
+ ":ping_pong:",
+ ":mountain_snow:",
+ ":camping:",
+ ":beach:",
+ ":construction_site:",
+ ":homes:",
+ ":cityscape:",
+ ":house_abandoned:",
+ ":classical_building:",
+ ":desert:",
+ ":island:",
+ ":park:",
+ ":stadium:",
+ ":house:",
+ ":house_with_garden:",
+ ":office:",
+ ":post_office:",
+ ":european_post_office:",
+ ":hospital:",
+ ":bank:",
+ ":atm:",
+ ":hotel:",
+ ":love_hotel:",
+ ":convenience_store:",
+ ":school:",
+ ":department_store:",
+ ":factory:",
+ ":izakaya_lantern:",
+ ":japanese_castle:",
+ ":european_castle:",
+ ":flag_white::rainbow:",
+ ":flag_white:",
+ ":flag_black::skull_crossbones:",
+ ":flag_black:",
+ ":rosette:",
+ ":label:",
+ ":badminton:",
+ ":bow_and_arrow:",
+ ":amphora:",
+ ":tone1:",
+ ":tone2:",
+ ":tone3:",
+ ":tone4:",
+ ":tone5:",
+ ":rat:",
+ ":mouse2:",
+ ":ox:",
+ ":water_buffalo:",
+ ":cow2:",
+ ":tiger2:",
+ ":leopard:",
+ ":rabbit2:",
+ ":cat2:",
+ ":dragon:",
+ ":crocodile:",
+ ":whale2:",
+ ":snail:",
+ ":snake:",
+ ":racehorse:",
+ ":ram:",
+ ":goat:",
+ ":sheep:",
+ ":monkey:",
+ ":rooster:",
+ ":chicken:",
+ ":dog2:",
+ ":pig2:",
+ ":boar:",
+ ":elephant:",
+ ":octopus:",
+ ":shell:",
+ ":bug:",
+ ":ant:",
+ ":bee:",
+ ":beetle:",
+ ":fish:",
+ ":tropical_fish:",
+ ":blowfish:",
+ ":turtle:",
+ ":hatching_chick:",
+ ":baby_chick:",
+ ":hatched_chick:",
+ ":bird:",
+ ":penguin:",
+ ":koala:",
+ ":poodle:",
+ ":dromedary_camel:",
+ ":camel:",
+ ":dolphin:",
+ ":mouse:",
+ ":cow:",
+ ":tiger:",
+ ":rabbit:",
+ ":cat:",
+ ":dragon_face:",
+ ":whale:",
+ ":horse:",
+ ":monkey_face:",
+ ":dog:",
+ ":pig:",
+ ":frog:",
+ ":hamster:",
+ ":wolf:",
+ ":bear:",
+ ":panda_face:",
+ ":pig_nose:",
+ ":feet:",
+ ":chipmunk:",
+ ":eyes:",
+ ":eye_in_speech_bubble:",
+ ":eye:",
+ ":ear_tone1:",
+ ":ear_tone2:",
+ ":ear_tone3:",
+ ":ear_tone4:",
+ ":ear_tone5:",
+ ":ear:",
+ ":nose_tone1:",
+ ":nose_tone2:",
+ ":nose_tone3:",
+ ":nose_tone4:",
+ ":nose_tone5:",
+ ":nose:",
+ ":lips:",
+ ":tongue:",
+ ":point_up_2_tone1:",
+ ":point_up_2_tone2:",
+ ":point_up_2_tone3:",
+ ":point_up_2_tone4:",
+ ":point_up_2_tone5:",
+ ":point_up_2:",
+ ":point_down_tone1:",
+ ":point_down_tone2:",
+ ":point_down_tone3:",
+ ":point_down_tone4:",
+ ":point_down_tone5:",
+ ":point_down:",
+ ":point_left_tone1:",
+ ":point_left_tone2:",
+ ":point_left_tone3:",
+ ":point_left_tone4:",
+ ":point_left_tone5:",
+ ":point_left:",
+ ":point_right_tone1:",
+ ":point_right_tone2:",
+ ":point_right_tone3:",
+ ":point_right_tone4:",
+ ":point_right_tone5:",
+ ":point_right:",
+ ":punch_tone1:",
+ ":punch_tone2:",
+ ":punch_tone3:",
+ ":punch_tone4:",
+ ":punch_tone5:",
+ ":punch:",
+ ":wave_tone1:",
+ ":wave_tone2:",
+ ":wave_tone3:",
+ ":wave_tone4:",
+ ":wave_tone5:",
+ ":wave:",
+ ":ok_hand_tone1:",
+ ":ok_hand_tone2:",
+ ":ok_hand_tone3:",
+ ":ok_hand_tone4:",
+ ":ok_hand_tone5:",
+ ":ok_hand:",
+ ":thumbsup_tone1:",
+ ":thumbsup_tone2:",
+ ":thumbsup_tone3:",
+ ":thumbsup_tone4:",
+ ":thumbsup_tone5:",
+ ":thumbsup:",
+ ":thumbsdown_tone1:",
+ ":thumbsdown_tone2:",
+ ":thumbsdown_tone3:",
+ ":thumbsdown_tone4:",
+ ":thumbsdown_tone5:",
+ ":thumbsdown:",
+ ":clap_tone1:",
+ ":clap_tone2:",
+ ":clap_tone3:",
+ ":clap_tone4:",
+ ":clap_tone5:",
+ ":clap:",
+ ":open_hands_tone1:",
+ ":open_hands_tone2:",
+ ":open_hands_tone3:",
+ ":open_hands_tone4:",
+ ":open_hands_tone5:",
+ ":open_hands:",
+ ":crown:",
+ ":womans_hat:",
+ ":eyeglasses:",
+ ":necktie:",
+ ":shirt:",
+ ":jeans:",
+ ":dress:",
+ ":kimono:",
+ ":bikini:",
+ ":womans_clothes:",
+ ":purse:",
+ ":handbag:",
+ ":pouch:",
+ ":mans_shoe:",
+ ":athletic_shoe:",
+ ":high_heel:",
+ ":sandal:",
+ ":boot:",
+ ":footprints:",
+ ":bust_in_silhouette:",
+ ":busts_in_silhouette:",
+ ":boy_tone1:",
+ ":boy_tone2:",
+ ":boy_tone3:",
+ ":boy_tone4:",
+ ":boy_tone5:",
+ ":boy:",
+ ":girl_tone1:",
+ ":girl_tone2:",
+ ":girl_tone3:",
+ ":girl_tone4:",
+ ":girl_tone5:",
+ ":girl:",
+ ":man_tone1::ear_of_rice:",
+ ":man_tone1::cooking:",
+ ":man_tone1::mortar_board:",
+ ":man_tone1::microphone:",
+ ":man_tone1::art:",
+ ":man_tone1::school:",
+ ":man_tone1::factory:",
+ ":man_tone1::computer:",
+ ":man_tone1::briefcase:",
+ ":man_tone1::wrench:",
+ ":man_tone1::microscope:",
+ ":man_tone1::rocket:",
+ ":man_tone1::fire_engine:",
+ ":man_tone1:⚕️",
+ ":man_tone1::scales:",
+ ":man_tone1::airplane:",
+ ":man_tone1:",
+ ":man_tone2::ear_of_rice:",
+ ":man_tone2::cooking:",
+ ":man_tone2::mortar_board:",
+ ":man_tone2::microphone:",
+ ":man_tone2::art:",
+ ":man_tone2::school:",
+ ":man_tone2::factory:",
+ ":man_tone2::computer:",
+ ":man_tone2::briefcase:",
+ ":man_tone2::wrench:",
+ ":man_tone2::microscope:",
+ ":man_tone2::rocket:",
+ ":man_tone2::fire_engine:",
+ ":man_tone2:⚕️",
+ ":man_tone2::scales:",
+ ":man_tone2::airplane:",
+ ":man_tone2:",
+ ":man_tone3::ear_of_rice:",
+ ":man_tone3::cooking:",
+ ":man_tone3::mortar_board:",
+ ":man_tone3::microphone:",
+ ":man_tone3::art:",
+ ":man_tone3::school:",
+ ":man_tone3::factory:",
+ ":man_tone3::computer:",
+ ":man_tone3::briefcase:",
+ ":man_tone3::wrench:",
+ ":man_tone3::microscope:",
+ ":man_tone3::rocket:",
+ ":man_tone3::fire_engine:",
+ ":man_tone3:⚕️",
+ ":man_tone3::scales:",
+ ":man_tone3::airplane:",
+ ":man_tone3:",
+ ":man_tone4::ear_of_rice:",
+ ":man_tone4::cooking:",
+ ":man_tone4::mortar_board:",
+ ":man_tone4::microphone:",
+ ":man_tone4::art:",
+ ":man_tone4::school:",
+ ":man_tone4::factory:",
+ ":man_tone4::computer:",
+ ":man_tone4::briefcase:",
+ ":man_tone4::wrench:",
+ ":man_tone4::microscope:",
+ ":man_tone4::rocket:",
+ ":man_tone4::fire_engine:",
+ ":man_tone4:⚕️",
+ ":man_tone4::scales:",
+ ":man_tone4::airplane:",
+ ":man_tone4:",
+ ":man_tone5::ear_of_rice:",
+ ":man_tone5::cooking:",
+ ":man_tone5::mortar_board:",
+ ":man_tone5::microphone:",
+ ":man_tone5::art:",
+ ":man_tone5::school:",
+ ":man_tone5::factory:",
+ ":man_tone5::computer:",
+ ":man_tone5::briefcase:",
+ ":man_tone5::wrench:",
+ ":man_tone5::microscope:",
+ ":man_tone5::rocket:",
+ ":man_tone5::fire_engine:",
+ ":man_tone5:⚕️",
+ ":man_tone5::scales:",
+ ":man_tone5::airplane:",
+ ":man_tone5:",
+ ":man::ear_of_rice:",
+ ":man::cooking:",
+ ":man::mortar_board:",
+ ":man::microphone:",
+ ":man::art:",
+ ":man::school:",
+ ":man::factory:",
+ ":man::boy::boy:",
+ ":man::boy:",
+ ":man::girl::boy:",
+ ":man::girl::girl:",
+ ":man::girl:",
+ ":family_mmbb:",
+ ":family_mmb:",
+ ":family_mmgb:",
+ ":family_mmgg:",
+ ":family_mmg:",
+ ":family_mwbb:",
+ ":man::woman::boy:",
+ ":family_mwgb:",
+ ":family_mwgg:",
+ ":family_mwg:",
+ ":man::computer:",
+ ":man::briefcase:",
+ ":man::wrench:",
+ ":man::microscope:",
+ ":man::rocket:",
+ ":man::fire_engine:",
+ ":man:⚕️",
+ ":man::scales:",
+ ":man::airplane:",
+ ":couple_mm:",
+ ":kiss_mm:",
+ ":man:",
+ ":woman_tone1::ear_of_rice:",
+ ":woman_tone1::cooking:",
+ ":woman_tone1::mortar_board:",
+ ":woman_tone1::microphone:",
+ ":woman_tone1::art:",
+ ":woman_tone1::school:",
+ ":woman_tone1::factory:",
+ ":woman_tone1::computer:",
+ ":woman_tone1::briefcase:",
+ ":woman_tone1::wrench:",
+ ":woman_tone1::microscope:",
+ ":woman_tone1::rocket:",
+ ":woman_tone1::fire_engine:",
+ ":woman_tone1:⚕️",
+ ":woman_tone1::scales:",
+ ":woman_tone1::airplane:",
+ ":woman_tone1:",
+ ":woman_tone2::ear_of_rice:",
+ ":woman_tone2::cooking:",
+ ":woman_tone2::mortar_board:",
+ ":woman_tone2::microphone:",
+ ":woman_tone2::art:",
+ ":woman_tone2::school:",
+ ":woman_tone2::factory:",
+ ":woman_tone2::computer:",
+ ":woman_tone2::briefcase:",
+ ":woman_tone2::wrench:",
+ ":woman_tone2::microscope:",
+ ":woman_tone2::rocket:",
+ ":woman_tone2::fire_engine:",
+ ":woman_tone2:⚕️",
+ ":woman_tone2::scales:",
+ ":woman_tone2::airplane:",
+ ":woman_tone2:",
+ ":woman_tone3::ear_of_rice:",
+ ":woman_tone3::cooking:",
+ ":woman_tone3::mortar_board:",
+ ":woman_tone3::microphone:",
+ ":woman_tone3::art:",
+ ":woman_tone3::school:",
+ ":woman_tone3::factory:",
+ ":woman_tone3::computer:",
+ ":woman_tone3::briefcase:",
+ ":woman_tone3::wrench:",
+ ":woman_tone3::microscope:",
+ ":woman_tone3::rocket:",
+ ":woman_tone3::fire_engine:",
+ ":woman_tone3:⚕️",
+ ":woman_tone3::scales:",
+ ":woman_tone3::airplane:",
+ ":woman_tone3:",
+ ":woman_tone4::ear_of_rice:",
+ ":woman_tone4::cooking:",
+ ":woman_tone4::mortar_board:",
+ ":woman_tone4::microphone:",
+ ":woman_tone4::art:",
+ ":woman_tone4::school:",
+ ":woman_tone4::factory:",
+ ":woman_tone4::computer:",
+ ":woman_tone4::briefcase:",
+ ":woman_tone4::wrench:",
+ ":woman_tone4::microscope:",
+ ":woman_tone4::rocket:",
+ ":woman_tone4::fire_engine:",
+ ":woman_tone4:⚕️",
+ ":woman_tone4::scales:",
+ ":woman_tone4::airplane:",
+ ":woman_tone4:",
+ ":woman_tone5::ear_of_rice:",
+ ":woman_tone5::cooking:",
+ ":woman_tone5::mortar_board:",
+ ":woman_tone5::microphone:",
+ ":woman_tone5::art:",
+ ":woman_tone5::school:",
+ ":woman_tone5::factory:",
+ ":woman_tone5::computer:",
+ ":woman_tone5::briefcase:",
+ ":woman_tone5::wrench:",
+ ":woman_tone5::microscope:",
+ ":woman_tone5::rocket:",
+ ":woman_tone5::fire_engine:",
+ ":woman_tone5:⚕️",
+ ":woman_tone5::scales:",
+ ":woman_tone5::airplane:",
+ ":woman_tone5:",
+ ":woman::ear_of_rice:",
+ ":woman::cooking:",
+ ":woman::mortar_board:",
+ ":woman::microphone:",
+ ":woman::art:",
+ ":woman::school:",
+ ":woman::factory:",
+ ":woman::boy::boy:",
+ ":woman::boy:",
+ ":woman::girl::boy:",
+ ":woman::girl::girl:",
+ ":woman::girl:",
+ ":family_wwbb:",
+ ":family_wwb:",
+ ":family_wwgb:",
+ ":family_wwgg:",
+ ":family_wwg:",
+ ":woman::computer:",
+ ":woman::briefcase:",
+ ":woman::wrench:",
+ ":woman::microscope:",
+ ":woman::rocket:",
+ ":woman::fire_engine:",
+ ":woman:⚕️",
+ ":woman::scales:",
+ ":woman::airplane:",
+ ":woman::heart::man:",
+ ":couple_ww:",
+ ":woman::heart::kiss::man:",
+ ":kiss_ww:",
+ ":woman:",
+ ":family::tone1:",
+ ":family::tone2:",
+ ":family::tone3:",
+ ":family::tone4:",
+ ":family::tone5:",
+ ":family:",
+ ":couple::tone1:",
+ ":couple::tone2:",
+ ":couple::tone3:",
+ ":couple::tone4:",
+ ":couple::tone5:",
+ ":couple:",
+ ":two_men_holding_hands::tone1:",
+ ":two_men_holding_hands::tone2:",
+ ":two_men_holding_hands::tone3:",
+ ":two_men_holding_hands::tone4:",
+ ":two_men_holding_hands::tone5:",
+ ":two_men_holding_hands:",
+ ":two_women_holding_hands::tone1:",
+ ":two_women_holding_hands::tone2:",
+ ":two_women_holding_hands::tone3:",
+ ":two_women_holding_hands::tone4:",
+ ":two_women_holding_hands::tone5:",
+ ":two_women_holding_hands:",
+ ":cop_tone1:♀️",
+ ":cop_tone1:♂️",
+ ":cop_tone1:",
+ ":cop_tone2:♀️",
+ ":cop_tone2:♂️",
+ ":cop_tone2:",
+ ":cop_tone3:♀️",
+ ":cop_tone3:♂️",
+ ":cop_tone3:",
+ ":cop_tone4:♀️",
+ ":cop_tone4:♂️",
+ ":cop_tone4:",
+ ":cop_tone5:♀️",
+ ":cop_tone5:♂️",
+ ":cop_tone5:",
+ ":cop:♀️",
+ ":cop:♂️",
+ ":cop:",
+ ":dancers::tone1:♀️",
+ ":dancers::tone1:♂️",
+ ":dancers::tone1:",
+ ":dancers::tone2:♀️",
+ ":dancers::tone2:♂️",
+ ":dancers::tone2:",
+ ":dancers::tone3:♀️",
+ ":dancers::tone3:♂️",
+ ":dancers::tone3:",
+ ":dancers::tone4:♀️",
+ ":dancers::tone4:♂️",
+ ":dancers::tone4:",
+ ":dancers::tone5:♀️",
+ ":dancers::tone5:♂️",
+ ":dancers::tone5:",
+ ":dancers:♀️",
+ ":dancers:♂️",
+ ":dancers:",
+ ":bride_with_veil_tone1:",
+ ":bride_with_veil_tone2:",
+ ":bride_with_veil_tone3:",
+ ":bride_with_veil_tone4:",
+ ":bride_with_veil_tone5:",
+ ":bride_with_veil:",
+ ":person_with_blond_hair_tone1:♀️",
+ ":person_with_blond_hair_tone1:♂️",
+ ":person_with_blond_hair_tone1:",
+ ":person_with_blond_hair_tone2:♀️",
+ ":person_with_blond_hair_tone2:♂️",
+ ":person_with_blond_hair_tone2:",
+ ":person_with_blond_hair_tone3:♀️",
+ ":person_with_blond_hair_tone3:♂️",
+ ":person_with_blond_hair_tone3:",
+ ":person_with_blond_hair_tone4:♀️",
+ ":person_with_blond_hair_tone4:♂️",
+ ":person_with_blond_hair_tone4:",
+ ":person_with_blond_hair_tone5:♀️",
+ ":person_with_blond_hair_tone5:♂️",
+ ":person_with_blond_hair_tone5:",
+ ":person_with_blond_hair:♀️",
+ ":person_with_blond_hair:♂️",
+ ":person_with_blond_hair:",
+ ":man_with_gua_pi_mao_tone1:",
+ ":man_with_gua_pi_mao_tone2:",
+ ":man_with_gua_pi_mao_tone3:",
+ ":man_with_gua_pi_mao_tone4:",
+ ":man_with_gua_pi_mao_tone5:",
+ ":man_with_gua_pi_mao:",
+ ":man_with_turban_tone1:♀️",
+ ":man_with_turban_tone1:♂️",
+ ":man_with_turban_tone1:",
+ ":man_with_turban_tone2:♀️",
+ ":man_with_turban_tone2:♂️",
+ ":man_with_turban_tone2:",
+ ":man_with_turban_tone3:♀️",
+ ":man_with_turban_tone3:♂️",
+ ":man_with_turban_tone3:",
+ ":man_with_turban_tone4:♀️",
+ ":man_with_turban_tone4:♂️",
+ ":man_with_turban_tone4:",
+ ":man_with_turban_tone5:♀️",
+ ":man_with_turban_tone5:♂️",
+ ":man_with_turban_tone5:",
+ ":man_with_turban:♀️",
+ ":man_with_turban:♂️",
+ ":man_with_turban:",
+ ":older_man_tone1:",
+ ":older_man_tone2:",
+ ":older_man_tone3:",
+ ":older_man_tone4:",
+ ":older_man_tone5:",
+ ":older_man:",
+ ":older_woman_tone1:",
+ ":older_woman_tone2:",
+ ":older_woman_tone3:",
+ ":older_woman_tone4:",
+ ":older_woman_tone5:",
+ ":older_woman:",
+ ":baby_tone1:",
+ ":baby_tone2:",
+ ":baby_tone3:",
+ ":baby_tone4:",
+ ":baby_tone5:",
+ ":baby:",
+ ":construction_worker_tone1:♀️",
+ ":construction_worker_tone1:♂️",
+ ":construction_worker_tone1:",
+ ":construction_worker_tone2:♀️",
+ ":construction_worker_tone2:♂️",
+ ":construction_worker_tone2:",
+ ":construction_worker_tone3:♀️",
+ ":construction_worker_tone3:♂️",
+ ":construction_worker_tone3:",
+ ":construction_worker_tone4:♀️",
+ ":construction_worker_tone4:♂️",
+ ":construction_worker_tone4:",
+ ":construction_worker_tone5:♀️",
+ ":construction_worker_tone5:♂️",
+ ":construction_worker_tone5:",
+ ":construction_worker:♀️",
+ ":construction_worker:♂️",
+ ":construction_worker:",
+ ":princess_tone1:",
+ ":princess_tone2:",
+ ":princess_tone3:",
+ ":princess_tone4:",
+ ":princess_tone5:",
+ ":princess:",
+ ":japanese_ogre:",
+ ":japanese_goblin:",
+ ":ghost:",
+ ":angel_tone1:",
+ ":angel_tone2:",
+ ":angel_tone3:",
+ ":angel_tone4:",
+ ":angel_tone5:",
+ ":angel:",
+ ":alien:",
+ ":space_invader:",
+ ":imp:",
+ ":skull:",
+ ":information_desk_person_tone1:♀️",
+ ":information_desk_person_tone1:♂️",
+ ":information_desk_person_tone1:",
+ ":information_desk_person_tone2:♀️",
+ ":information_desk_person_tone2:♂️",
+ ":information_desk_person_tone2:",
+ ":information_desk_person_tone3:♀️",
+ ":information_desk_person_tone3:♂️",
+ ":information_desk_person_tone3:",
+ ":information_desk_person_tone4:♀️",
+ ":information_desk_person_tone4:♂️",
+ ":information_desk_person_tone4:",
+ ":information_desk_person_tone5:♀️",
+ ":information_desk_person_tone5:♂️",
+ ":information_desk_person_tone5:",
+ ":information_desk_person:♀️",
+ ":information_desk_person:♂️",
+ ":information_desk_person:",
+ ":guardsman_tone1:♀️",
+ ":guardsman_tone1:♂️",
+ ":guardsman_tone1:",
+ ":guardsman_tone2:♀️",
+ ":guardsman_tone2:♂️",
+ ":guardsman_tone2:",
+ ":guardsman_tone3:♀️",
+ ":guardsman_tone3:♂️",
+ ":guardsman_tone3:",
+ ":guardsman_tone4:♀️",
+ ":guardsman_tone4:♂️",
+ ":guardsman_tone4:",
+ ":guardsman_tone5:♀️",
+ ":guardsman_tone5:♂️",
+ ":guardsman_tone5:",
+ ":guardsman:♀️",
+ ":guardsman:♂️",
+ ":guardsman:",
+ ":dancer_tone1:",
+ ":dancer_tone2:",
+ ":dancer_tone3:",
+ ":dancer_tone4:",
+ ":dancer_tone5:",
+ ":dancer:",
+ ":lipstick:",
+ ":nail_care_tone1:",
+ ":nail_care_tone2:",
+ ":nail_care_tone3:",
+ ":nail_care_tone4:",
+ ":nail_care_tone5:",
+ ":nail_care:",
+ ":massage_tone1:♀️",
+ ":massage_tone1:♂️",
+ ":massage_tone1:",
+ ":massage_tone2:♀️",
+ ":massage_tone2:♂️",
+ ":massage_tone2:",
+ ":massage_tone3:♀️",
+ ":massage_tone3:♂️",
+ ":massage_tone3:",
+ ":massage_tone4:♀️",
+ ":massage_tone4:♂️",
+ ":massage_tone4:",
+ ":massage_tone5:♀️",
+ ":massage_tone5:♂️",
+ ":massage_tone5:",
+ ":massage:♀️",
+ ":massage:♂️",
+ ":massage:",
+ ":haircut_tone1:♀️",
+ ":haircut_tone1:♂️",
+ ":haircut_tone1:",
+ ":haircut_tone2:♀️",
+ ":haircut_tone2:♂️",
+ ":haircut_tone2:",
+ ":haircut_tone3:♀️",
+ ":haircut_tone3:♂️",
+ ":haircut_tone3:",
+ ":haircut_tone4:♀️",
+ ":haircut_tone4:♂️",
+ ":haircut_tone4:",
+ ":haircut_tone5:♀️",
+ ":haircut_tone5:♂️",
+ ":haircut_tone5:",
+ ":haircut:♀️",
+ ":haircut:♂️",
+ ":haircut:",
+ ":barber:",
+ ":syringe:",
+ ":pill:",
+ ":kiss:",
+ ":love_letter:",
+ ":ring:",
+ ":gem:",
+ ":couplekiss:",
+ ":bouquet:",
+ ":couple_with_heart:",
+ ":wedding:",
+ ":heartbeat:",
+ ":broken_heart:",
+ ":two_hearts:",
+ ":sparkling_heart:",
+ ":heartpulse:",
+ ":cupid:",
+ ":blue_heart:",
+ ":green_heart:",
+ ":yellow_heart:",
+ ":purple_heart:",
+ ":gift_heart:",
+ ":revolving_hearts:",
+ ":heart_decoration:",
+ ":diamond_shape_with_a_dot_inside:",
+ ":bulb:",
+ ":anger:",
+ ":bomb:",
+ ":zzz:",
+ ":boom:",
+ ":sweat_drops:",
+ ":droplet:",
+ ":dash:",
+ ":poop:",
+ ":muscle_tone1:",
+ ":muscle_tone2:",
+ ":muscle_tone3:",
+ ":muscle_tone4:",
+ ":muscle_tone5:",
+ ":muscle:",
+ ":dizzy:",
+ ":speech_balloon:",
+ ":thought_balloon:",
+ ":white_flower:",
+ ":100:",
+ ":moneybag:",
+ ":currency_exchange:",
+ ":heavy_dollar_sign:",
+ ":credit_card:",
+ ":yen:",
+ ":dollar:",
+ ":euro:",
+ ":pound:",
+ ":money_with_wings:",
+ ":chart:",
+ ":seat:",
+ ":computer:",
+ ":briefcase:",
+ ":minidisc:",
+ ":floppy_disk:",
+ ":cd:",
+ ":dvd:",
+ ":file_folder:",
+ ":open_file_folder:",
+ ":page_with_curl:",
+ ":page_facing_up:",
+ ":date:",
+ ":calendar:",
+ ":card_index:",
+ ":chart_with_upwards_trend:",
+ ":chart_with_downwards_trend:",
+ ":bar_chart:",
+ ":clipboard:",
+ ":pushpin:",
+ ":round_pushpin:",
+ ":paperclip:",
+ ":straight_ruler:",
+ ":triangular_ruler:",
+ ":bookmark_tabs:",
+ ":ledger:",
+ ":notebook:",
+ ":notebook_with_decorative_cover:",
+ ":closed_book:",
+ ":book:",
+ ":green_book:",
+ ":blue_book:",
+ ":orange_book:",
+ ":books:",
+ ":name_badge:",
+ ":scroll:",
+ ":pencil:",
+ ":telephone_receiver:",
+ ":pager:",
+ ":fax:",
+ ":satellite:",
+ ":loudspeaker:",
+ ":mega:",
+ ":outbox_tray:",
+ ":inbox_tray:",
+ ":package:",
+ ":e-mail:",
+ ":incoming_envelope:",
+ ":envelope_with_arrow:",
+ ":mailbox_closed:",
+ ":mailbox:",
+ ":mailbox_with_mail:",
+ ":mailbox_with_no_mail:",
+ ":postbox:",
+ ":postal_horn:",
+ ":newspaper:",
+ ":iphone:",
+ ":calling:",
+ ":vibration_mode:",
+ ":mobile_phone_off:",
+ ":no_mobile_phones:",
+ ":signal_strength:",
+ ":camera:",
+ ":camera_with_flash:",
+ ":video_camera:",
+ ":tv:",
+ ":radio:",
+ ":vhs:",
+ ":projector:",
+ ":prayer_beads:",
+ ":twisted_rightwards_arrows:",
+ ":repeat:",
+ ":repeat_one:",
+ ":arrows_clockwise:",
+ ":arrows_counterclockwise:",
+ ":low_brightness:",
+ ":high_brightness:",
+ ":mute:",
+ ":speaker:",
+ ":sound:",
+ ":loud_sound:",
+ ":battery:",
+ ":electric_plug:",
+ ":mag:",
+ ":mag_right:",
+ ":lock_with_ink_pen:",
+ ":closed_lock_with_key:",
+ ":key:",
+ ":lock:",
+ ":unlock:",
+ ":bell:",
+ ":no_bell:",
+ ":bookmark:",
+ ":link:",
+ ":radio_button:",
+ ":back:",
+ ":end:",
+ ":on:",
+ ":soon:",
+ ":top:",
+ ":underage:",
+ ":keycap_ten:",
+ ":capital_abcd:",
+ ":abcd:",
+ ":1234:",
+ ":symbols:",
+ ":abc:",
+ ":fire:",
+ ":flashlight:",
+ ":wrench:",
+ ":hammer:",
+ ":nut_and_bolt:",
+ ":knife:",
+ ":gun:",
+ ":microscope:",
+ ":telescope:",
+ ":crystal_ball:",
+ ":six_pointed_star:",
+ ":beginner:",
+ ":trident:",
+ ":black_square_button:",
+ ":white_square_button:",
+ ":red_circle:",
+ ":large_blue_circle:",
+ ":large_orange_diamond:",
+ ":large_blue_diamond:",
+ ":small_orange_diamond:",
+ ":small_blue_diamond:",
+ ":small_red_triangle:",
+ ":small_red_triangle_down:",
+ ":arrow_up_small:",
+ ":arrow_down_small:",
+ ":om_symbol:",
+ ":dove:",
+ ":kaaba:",
+ ":mosque:",
+ ":synagogue:",
+ ":menorah:",
+ ":clock1:",
+ ":clock2:",
+ ":clock3:",
+ ":clock4:",
+ ":clock5:",
+ ":clock6:",
+ ":clock7:",
+ ":clock8:",
+ ":clock9:",
+ ":clock10:",
+ ":clock11:",
+ ":clock12:",
+ ":clock130:",
+ ":clock230:",
+ ":clock330:",
+ ":clock430:",
+ ":clock530:",
+ ":clock630:",
+ ":clock730:",
+ ":clock830:",
+ ":clock930:",
+ ":clock1030:",
+ ":clock1130:",
+ ":clock1230:",
+ ":candle:",
+ ":clock:",
+ ":hole:",
+ ":levitate::tone1:",
+ ":levitate::tone2:",
+ ":levitate::tone3:",
+ ":levitate::tone4:",
+ ":levitate::tone5:",
+ ":levitate:",
+ ":spy_tone1:♀️",
+ ":spy_tone1:♂️",
+ ":spy_tone1:",
+ ":spy_tone2:♀️",
+ ":spy_tone2:♂️",
+ ":spy_tone2:",
+ ":spy_tone3:♀️",
+ ":spy_tone3:♂️",
+ ":spy_tone3:",
+ ":spy_tone4:♀️",
+ ":spy_tone4:♂️",
+ ":spy_tone4:",
+ ":spy_tone5:♀️",
+ ":spy_tone5:♂️",
+ ":spy_tone5:",
+ ":spy:♀️",
+ ":spy:♂️",
+ ":spy:",
+ ":dark_sunglasses:",
+ ":spider:",
+ ":spider_web:",
+ ":joystick:",
+ ":man_dancing_tone1:",
+ ":man_dancing_tone2:",
+ ":man_dancing_tone3:",
+ ":man_dancing_tone4:",
+ ":man_dancing_tone5:",
+ ":man_dancing:",
+ ":paperclips:",
+ ":pen_ballpoint:",
+ ":pen_fountain:",
+ ":paintbrush:",
+ ":crayon:",
+ ":hand_splayed_tone1:",
+ ":hand_splayed_tone2:",
+ ":hand_splayed_tone3:",
+ ":hand_splayed_tone4:",
+ ":hand_splayed_tone5:",
+ ":hand_splayed:",
+ ":middle_finger_tone1:",
+ ":middle_finger_tone2:",
+ ":middle_finger_tone3:",
+ ":middle_finger_tone4:",
+ ":middle_finger_tone5:",
+ ":middle_finger:",
+ ":vulcan_tone1:",
+ ":vulcan_tone2:",
+ ":vulcan_tone3:",
+ ":vulcan_tone4:",
+ ":vulcan_tone5:",
+ ":vulcan:",
+ ":black_heart:",
+ ":desktop:",
+ ":printer:",
+ ":mouse_three_button:",
+ ":trackball:",
+ ":frame_photo:",
+ ":dividers:",
+ ":card_box:",
+ ":file_cabinet:",
+ ":wastebasket:",
+ ":notepad_spiral:",
+ ":calendar_spiral:",
+ ":compression:",
+ ":key2:",
+ ":newspaper2:",
+ ":dagger:",
+ ":speaking_head:",
+ ":speech_left:",
+ ":anger_right:",
+ ":ballot_box:",
+ ":map:",
+ ":mount_fuji:",
+ ":tokyo_tower:",
+ ":statue_of_liberty:",
+ ":japan:",
+ ":moyai:",
+ ":grinning:",
+ ":grin:",
+ ":joy:",
+ ":smiley:",
+ ":smile:",
+ ":sweat_smile:",
+ ":laughing:",
+ ":innocent:",
+ ":smiling_imp:",
+ ":wink:",
+ ":blush:",
+ ":yum:",
+ ":relieved:",
+ ":heart_eyes:",
+ ":sunglasses:",
+ ":smirk:",
+ ":neutral_face:",
+ ":expressionless:",
+ ":unamused:",
+ ":sweat:",
+ ":pensive:",
+ ":confused:",
+ ":confounded:",
+ ":kissing:",
+ ":kissing_heart:",
+ ":kissing_smiling_eyes:",
+ ":kissing_closed_eyes:",
+ ":stuck_out_tongue:",
+ ":stuck_out_tongue_winking_eye:",
+ ":stuck_out_tongue_closed_eyes:",
+ ":disappointed:",
+ ":worried:",
+ ":angry:",
+ ":rage:",
+ ":cry:",
+ ":persevere:",
+ ":triumph:",
+ ":disappointed_relieved:",
+ ":frowning:",
+ ":anguished:",
+ ":fearful:",
+ ":weary:",
+ ":sleepy:",
+ ":tired_face:",
+ ":grimacing:",
+ ":sob:",
+ ":open_mouth:",
+ ":hushed:",
+ ":cold_sweat:",
+ ":scream:",
+ ":astonished:",
+ ":flushed:",
+ ":sleeping:",
+ ":dizzy_face:",
+ ":no_mouth:",
+ ":mask:",
+ ":smile_cat:",
+ ":joy_cat:",
+ ":smiley_cat:",
+ ":heart_eyes_cat:",
+ ":smirk_cat:",
+ ":kissing_cat:",
+ ":pouting_cat:",
+ ":crying_cat_face:",
+ ":scream_cat:",
+ ":slight_frown:",
+ ":slight_smile:",
+ ":upside_down:",
+ ":rolling_eyes:",
+ ":no_good_tone1:♀️",
+ ":no_good_tone1:♂️",
+ ":no_good_tone1:",
+ ":no_good_tone2:♀️",
+ ":no_good_tone2:♂️",
+ ":no_good_tone2:",
+ ":no_good_tone3:♀️",
+ ":no_good_tone3:♂️",
+ ":no_good_tone3:",
+ ":no_good_tone4:♀️",
+ ":no_good_tone4:♂️",
+ ":no_good_tone4:",
+ ":no_good_tone5:♀️",
+ ":no_good_tone5:♂️",
+ ":no_good_tone5:",
+ ":no_good:♀️",
+ ":no_good:♂️",
+ ":no_good:",
+ ":ok_woman_tone1:♀️",
+ ":ok_woman_tone1:♂️",
+ ":ok_woman_tone1:",
+ ":ok_woman_tone2:♀️",
+ ":ok_woman_tone2:♂️",
+ ":ok_woman_tone2:",
+ ":ok_woman_tone3:♀️",
+ ":ok_woman_tone3:♂️",
+ ":ok_woman_tone3:",
+ ":ok_woman_tone4:♀️",
+ ":ok_woman_tone4:♂️",
+ ":ok_woman_tone4:",
+ ":ok_woman_tone5:♀️",
+ ":ok_woman_tone5:♂️",
+ ":ok_woman_tone5:",
+ ":ok_woman:♀️",
+ ":ok_woman:♂️",
+ ":ok_woman:",
+ ":bow_tone1:♀️",
+ ":bow_tone1:♂️",
+ ":bow_tone1:",
+ ":bow_tone2:♀️",
+ ":bow_tone2:♂️",
+ ":bow_tone2:",
+ ":bow_tone3:♀️",
+ ":bow_tone3:♂️",
+ ":bow_tone3:",
+ ":bow_tone4:♀️",
+ ":bow_tone4:♂️",
+ ":bow_tone4:",
+ ":bow_tone5:♀️",
+ ":bow_tone5:♂️",
+ ":bow_tone5:",
+ ":bow:♀️",
+ ":bow:♂️",
+ ":bow:",
+ ":see_no_evil:",
+ ":hear_no_evil:",
+ ":speak_no_evil:",
+ ":raising_hand_tone1:♀️",
+ ":raising_hand_tone1:♂️",
+ ":raising_hand_tone1:",
+ ":raising_hand_tone2:♀️",
+ ":raising_hand_tone2:♂️",
+ ":raising_hand_tone2:",
+ ":raising_hand_tone3:♀️",
+ ":raising_hand_tone3:♂️",
+ ":raising_hand_tone3:",
+ ":raising_hand_tone4:♀️",
+ ":raising_hand_tone4:♂️",
+ ":raising_hand_tone4:",
+ ":raising_hand_tone5:♀️",
+ ":raising_hand_tone5:♂️",
+ ":raising_hand_tone5:",
+ ":raising_hand:♀️",
+ ":raising_hand:♂️",
+ ":raising_hand:",
+ ":raised_hands_tone1:",
+ ":raised_hands_tone2:",
+ ":raised_hands_tone3:",
+ ":raised_hands_tone4:",
+ ":raised_hands_tone5:",
+ ":raised_hands:",
+ ":person_frowning_tone1:♀️",
+ ":person_frowning_tone1:♂️",
+ ":person_frowning_tone1:",
+ ":person_frowning_tone2:♀️",
+ ":person_frowning_tone2:♂️",
+ ":person_frowning_tone2:",
+ ":person_frowning_tone3:♀️",
+ ":person_frowning_tone3:♂️",
+ ":person_frowning_tone3:",
+ ":person_frowning_tone4:♀️",
+ ":person_frowning_tone4:♂️",
+ ":person_frowning_tone4:",
+ ":person_frowning_tone5:♀️",
+ ":person_frowning_tone5:♂️",
+ ":person_frowning_tone5:",
+ ":person_frowning:♀️",
+ ":person_frowning:♂️",
+ ":person_frowning:",
+ ":person_with_pouting_face_tone1:♀️",
+ ":person_with_pouting_face_tone1:♂️",
+ ":person_with_pouting_face_tone1:",
+ ":person_with_pouting_face_tone2:♀️",
+ ":person_with_pouting_face_tone2:♂️",
+ ":person_with_pouting_face_tone2:",
+ ":person_with_pouting_face_tone3:♀️",
+ ":person_with_pouting_face_tone3:♂️",
+ ":person_with_pouting_face_tone3:",
+ ":person_with_pouting_face_tone4:♀️",
+ ":person_with_pouting_face_tone4:♂️",
+ ":person_with_pouting_face_tone4:",
+ ":person_with_pouting_face_tone5:♀️",
+ ":person_with_pouting_face_tone5:♂️",
+ ":person_with_pouting_face_tone5:",
+ ":person_with_pouting_face:♀️",
+ ":person_with_pouting_face:♂️",
+ ":person_with_pouting_face:",
+ ":pray_tone1:",
+ ":pray_tone2:",
+ ":pray_tone3:",
+ ":pray_tone4:",
+ ":pray_tone5:",
+ ":pray:",
+ ":rocket:",
+ ":helicopter:",
+ ":steam_locomotive:",
+ ":railway_car:",
+ ":bullettrain_side:",
+ ":bullettrain_front:",
+ ":train2:",
+ ":metro:",
+ ":light_rail:",
+ ":station:",
+ ":tram:",
+ ":train:",
+ ":bus:",
+ ":oncoming_bus:",
+ ":trolleybus:",
+ ":busstop:",
+ ":minibus:",
+ ":ambulance:",
+ ":fire_engine:",
+ ":police_car:",
+ ":oncoming_police_car:",
+ ":taxi:",
+ ":oncoming_taxi:",
+ ":red_car:",
+ ":oncoming_automobile:",
+ ":blue_car:",
+ ":truck:",
+ ":articulated_lorry:",
+ ":tractor:",
+ ":monorail:",
+ ":mountain_railway:",
+ ":suspension_railway:",
+ ":mountain_cableway:",
+ ":aerial_tramway:",
+ ":ship:",
+ ":rowboat_tone1:♀️",
+ ":rowboat_tone1:♂️",
+ ":rowboat_tone1:",
+ ":rowboat_tone2:♀️",
+ ":rowboat_tone2:♂️",
+ ":rowboat_tone2:",
+ ":rowboat_tone3:♀️",
+ ":rowboat_tone3:♂️",
+ ":rowboat_tone3:",
+ ":rowboat_tone4:♀️",
+ ":rowboat_tone4:♂️",
+ ":rowboat_tone4:",
+ ":rowboat_tone5:♀️",
+ ":rowboat_tone5:♂️",
+ ":rowboat_tone5:",
+ ":rowboat:♀️",
+ ":rowboat:♂️",
+ ":rowboat:",
+ ":speedboat:",
+ ":traffic_light:",
+ ":vertical_traffic_light:",
+ ":construction:",
+ ":rotating_light:",
+ ":triangular_flag_on_post:",
+ ":door:",
+ ":no_entry_sign:",
+ ":smoking:",
+ ":no_smoking:",
+ ":put_litter_in_its_place:",
+ ":do_not_litter:",
+ ":potable_water:",
+ ":non-potable_water:",
+ ":bike:",
+ ":no_bicycles:",
+ ":bicyclist_tone1:♀️",
+ ":bicyclist_tone1:♂️",
+ ":bicyclist_tone1:",
+ ":bicyclist_tone2:♀️",
+ ":bicyclist_tone2:♂️",
+ ":bicyclist_tone2:",
+ ":bicyclist_tone3:♀️",
+ ":bicyclist_tone3:♂️",
+ ":bicyclist_tone3:",
+ ":bicyclist_tone4:♀️",
+ ":bicyclist_tone4:♂️",
+ ":bicyclist_tone4:",
+ ":bicyclist_tone5:♀️",
+ ":bicyclist_tone5:♂️",
+ ":bicyclist_tone5:",
+ ":bicyclist:♀️",
+ ":bicyclist:♂️",
+ ":bicyclist:",
+ ":mountain_bicyclist_tone1:♀️",
+ ":mountain_bicyclist_tone1:♂️",
+ ":mountain_bicyclist_tone1:",
+ ":mountain_bicyclist_tone2:♀️",
+ ":mountain_bicyclist_tone2:♂️",
+ ":mountain_bicyclist_tone2:",
+ ":mountain_bicyclist_tone3:♀️",
+ ":mountain_bicyclist_tone3:♂️",
+ ":mountain_bicyclist_tone3:",
+ ":mountain_bicyclist_tone4:♀️",
+ ":mountain_bicyclist_tone4:♂️",
+ ":mountain_bicyclist_tone4:",
+ ":mountain_bicyclist_tone5:♀️",
+ ":mountain_bicyclist_tone5:♂️",
+ ":mountain_bicyclist_tone5:",
+ ":mountain_bicyclist:♀️",
+ ":mountain_bicyclist:♂️",
+ ":mountain_bicyclist:",
+ ":walking_tone1:♀️",
+ ":walking_tone1:♂️",
+ ":walking_tone1:",
+ ":walking_tone2:♀️",
+ ":walking_tone2:♂️",
+ ":walking_tone2:",
+ ":walking_tone3:♀️",
+ ":walking_tone3:♂️",
+ ":walking_tone3:",
+ ":walking_tone4:♀️",
+ ":walking_tone4:♂️",
+ ":walking_tone4:",
+ ":walking_tone5:♀️",
+ ":walking_tone5:♂️",
+ ":walking_tone5:",
+ ":walking:♀️",
+ ":walking:♂️",
+ ":walking:",
+ ":no_pedestrians:",
+ ":children_crossing:",
+ ":mens:",
+ ":womens:",
+ ":restroom:",
+ ":baby_symbol:",
+ ":toilet:",
+ ":wc:",
+ ":shower:",
+ ":bath_tone1:",
+ ":bath_tone2:",
+ ":bath_tone3:",
+ ":bath_tone4:",
+ ":bath_tone5:",
+ ":bath:",
+ ":bathtub:",
+ ":passport_control:",
+ ":customs:",
+ ":baggage_claim:",
+ ":left_luggage:",
+ ":couch:",
+ ":sleeping_accommodation::tone1:",
+ ":sleeping_accommodation::tone2:",
+ ":sleeping_accommodation::tone3:",
+ ":sleeping_accommodation::tone4:",
+ ":sleeping_accommodation::tone5:",
+ ":sleeping_accommodation:",
+ ":shopping_bags:",
+ ":bellhop:",
+ ":bed:",
+ ":place_of_worship:",
+ ":octagonal_sign:",
+ ":shopping_cart:",
+ ":tools:",
+ ":shield:",
+ ":oil:",
+ ":motorway:",
+ ":railway_track:",
+ ":motorboat:",
+ ":airplane_small:",
+ ":airplane_departure:",
+ ":airplane_arriving:",
+ ":satellite_orbital:",
+ ":cruise_ship:",
+ ":scooter:",
+ ":motor_scooter:",
+ ":canoe:",
+ ":zipper_mouth:",
+ ":money_mouth:",
+ ":thermometer_face:",
+ ":nerd:",
+ ":thinking:",
+ ":head_bandage:",
+ ":robot:",
+ ":hugging:",
+ ":metal_tone1:",
+ ":metal_tone2:",
+ ":metal_tone3:",
+ ":metal_tone4:",
+ ":metal_tone5:",
+ ":metal:",
+ ":call_me_tone1:",
+ ":call_me_tone2:",
+ ":call_me_tone3:",
+ ":call_me_tone4:",
+ ":call_me_tone5:",
+ ":call_me:",
+ ":raised_back_of_hand_tone1:",
+ ":raised_back_of_hand_tone2:",
+ ":raised_back_of_hand_tone3:",
+ ":raised_back_of_hand_tone4:",
+ ":raised_back_of_hand_tone5:",
+ ":raised_back_of_hand:",
+ ":left_facing_fist_tone1:",
+ ":left_facing_fist_tone2:",
+ ":left_facing_fist_tone3:",
+ ":left_facing_fist_tone4:",
+ ":left_facing_fist_tone5:",
+ ":left_facing_fist:",
+ ":right_facing_fist_tone1:",
+ ":right_facing_fist_tone2:",
+ ":right_facing_fist_tone3:",
+ ":right_facing_fist_tone4:",
+ ":right_facing_fist_tone5:",
+ ":right_facing_fist:",
+ ":handshake_tone1:",
+ ":handshake_tone2:",
+ ":handshake_tone3:",
+ ":handshake_tone4:",
+ ":handshake_tone5:",
+ ":handshake:",
+ ":fingers_crossed_tone1:",
+ ":fingers_crossed_tone2:",
+ ":fingers_crossed_tone3:",
+ ":fingers_crossed_tone4:",
+ ":fingers_crossed_tone5:",
+ ":fingers_crossed:",
+ ":cowboy:",
+ ":clown:",
+ ":nauseated_face:",
+ ":rofl:",
+ ":drooling_face:",
+ ":lying_face:",
+ ":face_palm_tone1:♀️",
+ ":face_palm_tone1:♂️",
+ ":face_palm_tone1:",
+ ":face_palm_tone2:♀️",
+ ":face_palm_tone2:♂️",
+ ":face_palm_tone2:",
+ ":face_palm_tone3:♀️",
+ ":face_palm_tone3:♂️",
+ ":face_palm_tone3:",
+ ":face_palm_tone4:♀️",
+ ":face_palm_tone4:♂️",
+ ":face_palm_tone4:",
+ ":face_palm_tone5:♀️",
+ ":face_palm_tone5:♂️",
+ ":face_palm_tone5:",
+ ":face_palm:♀️",
+ ":face_palm:♂️",
+ ":face_palm:",
+ ":sneezing_face:",
+ ":pregnant_woman_tone1:",
+ ":pregnant_woman_tone2:",
+ ":pregnant_woman_tone3:",
+ ":pregnant_woman_tone4:",
+ ":pregnant_woman_tone5:",
+ ":pregnant_woman:",
+ ":selfie_tone1:",
+ ":selfie_tone2:",
+ ":selfie_tone3:",
+ ":selfie_tone4:",
+ ":selfie_tone5:",
+ ":selfie:",
+ ":prince_tone1:",
+ ":prince_tone2:",
+ ":prince_tone3:",
+ ":prince_tone4:",
+ ":prince_tone5:",
+ ":prince:",
+ ":man_in_tuxedo_tone1:",
+ ":man_in_tuxedo_tone2:",
+ ":man_in_tuxedo_tone3:",
+ ":man_in_tuxedo_tone4:",
+ ":man_in_tuxedo_tone5:",
+ ":man_in_tuxedo:",
+ ":mrs_claus_tone1:",
+ ":mrs_claus_tone2:",
+ ":mrs_claus_tone3:",
+ ":mrs_claus_tone4:",
+ ":mrs_claus_tone5:",
+ ":mrs_claus:",
+ ":shrug_tone1:♀️",
+ ":shrug_tone1:♂️",
+ ":shrug_tone1:",
+ ":shrug_tone2:♀️",
+ ":shrug_tone2:♂️",
+ ":shrug_tone2:",
+ ":shrug_tone3:♀️",
+ ":shrug_tone3:♂️",
+ ":shrug_tone3:",
+ ":shrug_tone4:♀️",
+ ":shrug_tone4:♂️",
+ ":shrug_tone4:",
+ ":shrug_tone5:♀️",
+ ":shrug_tone5:♂️",
+ ":shrug_tone5:",
+ ":shrug:♀️",
+ ":shrug:♂️",
+ ":shrug:",
+ ":cartwheel_tone1:♀️",
+ ":cartwheel_tone1:♂️",
+ ":cartwheel_tone1:",
+ ":cartwheel_tone2:♀️",
+ ":cartwheel_tone2:♂️",
+ ":cartwheel_tone2:",
+ ":cartwheel_tone3:♀️",
+ ":cartwheel_tone3:♂️",
+ ":cartwheel_tone3:",
+ ":cartwheel_tone4:♀️",
+ ":cartwheel_tone4:♂️",
+ ":cartwheel_tone4:",
+ ":cartwheel_tone5:♀️",
+ ":cartwheel_tone5:♂️",
+ ":cartwheel_tone5:",
+ ":cartwheel:♀️",
+ ":cartwheel:♂️",
+ ":cartwheel:",
+ ":juggling_tone1:♀️",
+ ":juggling_tone1:♂️",
+ ":juggling_tone1:",
+ ":juggling_tone2:♀️",
+ ":juggling_tone2:♂️",
+ ":juggling_tone2:",
+ ":juggling_tone3:♀️",
+ ":juggling_tone3:♂️",
+ ":juggling_tone3:",
+ ":juggling_tone4:♀️",
+ ":juggling_tone4:♂️",
+ ":juggling_tone4:",
+ ":juggling_tone5:♀️",
+ ":juggling_tone5:♂️",
+ ":juggling_tone5:",
+ ":juggling:♀️",
+ ":juggling:♂️",
+ ":juggling:",
+ ":fencer:",
+ ":wrestlers_tone1:♀️",
+ ":wrestlers_tone1:♂️",
+ ":wrestlers_tone1:",
+ ":wrestlers_tone2:♀️",
+ ":wrestlers_tone2:♂️",
+ ":wrestlers_tone2:",
+ ":wrestlers_tone3:♀️",
+ ":wrestlers_tone3:♂️",
+ ":wrestlers_tone3:",
+ ":wrestlers_tone4:♀️",
+ ":wrestlers_tone4:♂️",
+ ":wrestlers_tone4:",
+ ":wrestlers_tone5:♀️",
+ ":wrestlers_tone5:♂️",
+ ":wrestlers_tone5:",
+ ":wrestlers:♀️",
+ ":wrestlers:♂️",
+ ":wrestlers:",
+ ":water_polo_tone1:♀️",
+ ":water_polo_tone1:♂️",
+ ":water_polo_tone1:",
+ ":water_polo_tone2:♀️",
+ ":water_polo_tone2:♂️",
+ ":water_polo_tone2:",
+ ":water_polo_tone3:♀️",
+ ":water_polo_tone3:♂️",
+ ":water_polo_tone3:",
+ ":water_polo_tone4:♀️",
+ ":water_polo_tone4:♂️",
+ ":water_polo_tone4:",
+ ":water_polo_tone5:♀️",
+ ":water_polo_tone5:♂️",
+ ":water_polo_tone5:",
+ ":water_polo:♀️",
+ ":water_polo:♂️",
+ ":water_polo:",
+ ":handball_tone1:♀️",
+ ":handball_tone1:♂️",
+ ":handball_tone1:",
+ ":handball_tone2:♀️",
+ ":handball_tone2:♂️",
+ ":handball_tone2:",
+ ":handball_tone3:♀️",
+ ":handball_tone3:♂️",
+ ":handball_tone3:",
+ ":handball_tone4:♀️",
+ ":handball_tone4:♂️",
+ ":handball_tone4:",
+ ":handball_tone5:♀️",
+ ":handball_tone5:♂️",
+ ":handball_tone5:",
+ ":handball:♀️",
+ ":handball:♂️",
+ ":handball:",
+ ":wilted_rose:",
+ ":drum:",
+ ":champagne_glass:",
+ ":tumbler_glass:",
+ ":spoon:",
+ ":goal:",
+ ":first_place:",
+ ":second_place:",
+ ":third_place:",
+ ":boxing_glove:",
+ ":martial_arts_uniform:",
+ ":croissant:",
+ ":avocado:",
+ ":cucumber:",
+ ":bacon:",
+ ":potato:",
+ ":carrot:",
+ ":french_bread:",
+ ":salad:",
+ ":shallow_pan_of_food:",
+ ":stuffed_flatbread:",
+ ":egg:",
+ ":milk:",
+ ":peanuts:",
+ ":kiwi:",
+ ":pancakes:",
+ ":crab:",
+ ":lion_face:",
+ ":scorpion:",
+ ":turkey:",
+ ":unicorn:",
+ ":eagle:",
+ ":duck:",
+ ":bat:",
+ ":shark:",
+ ":owl:",
+ ":fox:",
+ ":butterfly:",
+ ":deer:",
+ ":gorilla:",
+ ":lizard:",
+ ":rhino:",
+ ":shrimp:",
+ ":squid:",
+ ":cheese:",
+ ":bangbang:",
+ ":interrobang:",
+ ":tm:",
+ ":information_source:",
+ ":left_right_arrow:",
+ ":arrow_up_down:",
+ ":arrow_upper_left:",
+ ":arrow_upper_right:",
+ ":arrow_lower_right:",
+ ":arrow_lower_left:",
+ ":leftwards_arrow_with_hook:",
+ ":arrow_right_hook:",
+ ":hash:",
+ ":watch:",
+ ":hourglass:",
+ ":keyboard:",
+ ":eject:",
+ ":fast_forward:",
+ ":rewind:",
+ ":arrow_double_up:",
+ ":arrow_double_down:",
+ ":track_next:",
+ ":track_previous:",
+ ":play_pause:",
+ ":alarm_clock:",
+ ":stopwatch:",
+ ":timer:",
+ ":hourglass_flowing_sand:",
+ ":pause_button:",
+ ":stop_button:",
+ ":record_button:",
+ ":m:",
+ ":black_small_square:",
+ ":white_small_square:",
+ ":arrow_forward:",
+ ":arrow_backward:",
+ ":white_medium_square:",
+ ":black_medium_square:",
+ ":white_medium_small_square:",
+ ":black_medium_small_square:",
+ ":sunny:",
+ ":cloud:",
+ ":umbrella2:",
+ ":snowman2:",
+ ":comet:",
+ ":telephone:",
+ ":ballot_box_with_check:",
+ ":umbrella:",
+ ":coffee:",
+ ":shamrock:",
+ ":point_up_tone1:",
+ ":point_up_tone2:",
+ ":point_up_tone3:",
+ ":point_up_tone4:",
+ ":point_up_tone5:",
+ ":point_up:",
+ ":skull_crossbones:",
+ ":radioactive:",
+ ":biohazard:",
+ ":orthodox_cross:",
+ ":star_and_crescent:",
+ ":peace:",
+ ":yin_yang:",
+ ":wheel_of_dharma:",
+ ":frowning2:",
+ ":relaxed:",
+ "♀",
+ "♂",
+ ":aries:",
+ ":taurus:",
+ ":gemini:",
+ ":cancer:",
+ ":leo:",
+ ":virgo:",
+ ":libra:",
+ ":scorpius:",
+ ":sagittarius:",
+ ":capricorn:",
+ ":aquarius:",
+ ":pisces:",
+ ":spades:",
+ ":clubs:",
+ ":hearts:",
+ ":diamonds:",
+ ":hotsprings:",
+ ":recycle:",
+ ":wheelchair:",
+ ":hammer_pick:",
+ ":anchor:",
+ ":crossed_swords:",
+ "⚕",
+ ":scales:",
+ ":alembic:",
+ ":gear:",
+ ":atom:",
+ ":fleur-de-lis:",
+ ":warning:",
+ ":zap:",
+ ":white_circle:",
+ ":black_circle:",
+ ":coffin:",
+ ":urn:",
+ ":soccer:",
+ ":baseball:",
+ ":snowman:",
+ ":partly_sunny:",
+ ":thunder_cloud_rain:",
+ ":ophiuchus:",
+ ":pick:",
+ ":helmet_with_cross:",
+ ":chains:",
+ ":no_entry:",
+ ":shinto_shrine:",
+ ":church:",
+ ":mountain:",
+ ":beach_umbrella:",
+ ":fountain:",
+ ":golf:",
+ ":ferry:",
+ ":sailboat:",
+ ":skier::tone1:",
+ ":skier::tone2:",
+ ":skier::tone3:",
+ ":skier::tone4:",
+ ":skier::tone5:",
+ ":skier:",
+ ":ice_skate:",
+ ":basketball_player_tone1:♀️",
+ ":basketball_player_tone1:♂️",
+ ":basketball_player_tone1:",
+ ":basketball_player_tone2:♀️",
+ ":basketball_player_tone2:♂️",
+ ":basketball_player_tone2:",
+ ":basketball_player_tone3:♀️",
+ ":basketball_player_tone3:♂️",
+ ":basketball_player_tone3:",
+ ":basketball_player_tone4:♀️",
+ ":basketball_player_tone4:♂️",
+ ":basketball_player_tone4:",
+ ":basketball_player_tone5:♀️",
+ ":basketball_player_tone5:♂️",
+ ":basketball_player_tone5:",
+ ":basketball_player:♀️",
+ ":basketball_player:♂️",
+ ":basketball_player:",
+ ":tent:",
+ ":fuelpump:",
+ ":scissors:",
+ ":white_check_mark:",
+ ":airplane:",
+ ":envelope:",
+ ":fist_tone1:",
+ ":fist_tone2:",
+ ":fist_tone3:",
+ ":fist_tone4:",
+ ":fist_tone5:",
+ ":fist:",
+ ":raised_hand_tone1:",
+ ":raised_hand_tone2:",
+ ":raised_hand_tone3:",
+ ":raised_hand_tone4:",
+ ":raised_hand_tone5:",
+ ":raised_hand:",
+ ":v_tone1:",
+ ":v_tone2:",
+ ":v_tone3:",
+ ":v_tone4:",
+ ":v_tone5:",
+ ":v:",
+ ":writing_hand_tone1:",
+ ":writing_hand_tone2:",
+ ":writing_hand_tone3:",
+ ":writing_hand_tone4:",
+ ":writing_hand_tone5:",
+ ":writing_hand:",
+ ":pencil2:",
+ ":black_nib:",
+ ":heavy_check_mark:",
+ ":heavy_multiplication_x:",
+ ":cross:",
+ ":star_of_david:",
+ ":sparkles:",
+ ":eight_spoked_asterisk:",
+ ":eight_pointed_black_star:",
+ ":snowflake:",
+ ":sparkle:",
+ ":x:",
+ ":negative_squared_cross_mark:",
+ ":question:",
+ ":grey_question:",
+ ":grey_exclamation:",
+ ":exclamation:",
+ ":heart_exclamation:",
+ ":heart:",
+ ":heavy_plus_sign:",
+ ":heavy_minus_sign:",
+ ":heavy_division_sign:",
+ ":arrow_right:",
+ ":curly_loop:",
+ ":loop:",
+ ":arrow_heading_up:",
+ ":arrow_heading_down:",
+ ":asterisk:",
+ ":arrow_left:",
+ ":arrow_up:",
+ ":arrow_down:",
+ ":black_large_square:",
+ ":white_large_square:",
+ ":star:",
+ ":o:",
+ ":zero:",
+ ":wavy_dash:",
+ ":part_alternation_mark:",
+ ":one:",
+ ":two:",
+ ":congratulations:",
+ ":secret:",
+ ":three:",
+ ":four:",
+ ":five:",
+ ":six:",
+ ":seven:",
+ ":eight:",
+ ":nine:",
+ ":copyright:",
+ ":registered:",
+ ""
+];
+
+frappe.ui.emoji_map = (function() {
+ const map = {};
+ for(let i = 0; i < frappe.ui.emojis.length; i++) {
+ map[frappe.ui.emoji_keywords[i]] = frappe.ui.emojis[i];
+ }
+ return map;
+})();
\ No newline at end of file
diff --git a/frappe/public/less/desk.less b/frappe/public/less/desk.less
index 45bde29460..2ada74b8f7 100644
--- a/frappe/public/less/desk.less
+++ b/frappe/public/less/desk.less
@@ -591,6 +591,24 @@ a.progress-small {
}
}
+.note-hint-popover {
+ border-radius: 3px;
+ border-color: @border-color;
+ padding: 0;
+
+ .popover-content {
+ padding: 0;
+ }
+
+ .note-hint-item {
+ color: @text-color !important;
+ padding: 5px 8.8px !important;
+ }
+ .note-hint-item.active {
+ background-color: @btn-bg !important;
+ }
+}
+
.search-dialog {
.modal-dialog {
width: 768px;
From 7fa8148d33c74e9a4ffa8bc957c6a1dd89c37c04 Mon Sep 17 00:00:00 2001
From: Prateeksha Singh
Date: Fri, 28 Jul 2017 11:14:33 +0530
Subject: [PATCH 11/52] Graph additions (#3776)
* remove hardcoded height and width
* [graph] relative measures, offsets, generalise all base jobs
* Multiple datasets! (individually colored)
* [graph] Tooltips
* [graph] animate and change values
* [graph] percentage graph
* [graph] custom height, window resize refresh
* [graph] style changes
* [graph] update docs
* [graphs] make graphs.less
* [graphs] prefix classes with 'graph-', nest inside parent class
---
.eslintrc | 4 +-
.../assets/img/desk/animated_line_graph.gif | Bin 0 -> 306915 bytes
frappe/docs/assets/img/desk/bar_graph.png | Bin 30001 -> 27995 bytes
frappe/docs/assets/img/desk/line_graph.png | Bin 39700 -> 0 bytes
.../docs/assets/img/desk/line_graph_sales.png | Bin 0 -> 61751 bytes
.../docs/assets/img/desk/percentage_graph.png | Bin 0 -> 17452 bytes
.../docs/user/en/guides/desk/making_graphs.md | 149 +++--
frappe/public/build.json | 5 +-
frappe/public/css/form.css | 74 ---
frappe/public/css/graphs.css | 274 +++++++++
frappe/public/js/frappe/form/dashboard.js | 5 +-
frappe/public/js/frappe/ui/graph.js | 308 ----------
frappe/public/js/frappe/ui/graphs.js | 569 ++++++++++++++++++
.../js/frappe/views/reports/query_report.js | 2 +-
frappe/public/less/form.less | 109 +---
frappe/public/less/graphs.less | 319 ++++++++++
frappe/tests/test_goal.py | 2 +-
frappe/utils/goal.py | 26 +-
18 files changed, 1291 insertions(+), 555 deletions(-)
create mode 100644 frappe/docs/assets/img/desk/animated_line_graph.gif
delete mode 100644 frappe/docs/assets/img/desk/line_graph.png
create mode 100644 frappe/docs/assets/img/desk/line_graph_sales.png
create mode 100644 frappe/docs/assets/img/desk/percentage_graph.png
create mode 100644 frappe/public/css/graphs.css
delete mode 100644 frappe/public/js/frappe/ui/graph.js
create mode 100644 frappe/public/js/frappe/ui/graphs.js
create mode 100644 frappe/public/less/graphs.less
diff --git a/.eslintrc b/.eslintrc
index 44af7b458f..ade1623262 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -118,6 +118,8 @@
"getCookie": true,
"getCookies": true,
"get_url_arg": true,
- "QUnit": true
+ "QUnit": true,
+ "Snap": true,
+ "mina": true
}
}
diff --git a/frappe/docs/assets/img/desk/animated_line_graph.gif b/frappe/docs/assets/img/desk/animated_line_graph.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b0e7b212c6b7321d344c574a9d0a2b3e68ffc17
GIT binary patch
literal 306915
zcmWh!by$;M8(zRRVnGk7(J72>9UY<$MM4lqNeDIf-Or=lRDztIzk
zfs_)C5K#~b0~OfEcVBP*^IX@t&U-)SIrsg%4o>zarhW{t2JkmP7r+IWHhNgspF2_G
z?^+Xlh8}dLI?%l)#DgB@Ss&?D6>*jxajq%Sw>pAwH`4E3tpCHffIG2)%}Ez3;x5#O
z1eeB!lwA%fj|;gK7h0bb{xmfFS@NZdt5NNwn8uWtW>Q=)HQ`!X!rj!XHxiSRuP3Kw
zBr`ISUuIvwPP(2#x=zWxUPHOwpHE6jO>fLje@r4j%px!iu^{VZ
zNp5~&ZhdiH4y~a0c0qq-!E{YwOGQ!P&C=WSvhvchs)n)`)n()9<^8p{-X+{wctodH
zRZc#t>VHuEqM>^ASxw!8dsFeXj3;&XYU(GG>!)HHW{R68ZZs{wc))6YFkJRvEaSms
z>%&Kn9*!40dfNJElgSv#XN+bt-q9H28O=|gG>_&z8!dW1QvQ58w`KTM%iq4%mX_Al
zo)@o}FGea}%oe?v>w3wqYG*gRnyz>~(EED2rK6*(W4gBEQ$^>yhg~yox>i|Tzut5Y
zjC6Cydiq$sn$QD*6RZ!<`e$1D=SKzySVODNhCjX>{@%o9kB;om
zjDDIN{Wdka^I>e_!`OV!`1bROm97cy!UT75a&}>IeQ|P=Ik~qmH8c1A!|eOnkMEbK
zK1@%~%uLU0bj{9=&8`m2{%N26vp6^Rac+O%S##Z(RzwU3W9^e;eb@#*S{`l(t_O}D9Z?6B|
zTL1HPegEV7{@VKf);jmY_x1JfKX<?kYJNtkB?CktGz~086z2ATK
zxPSI{|8V#J{@ee%yY+YX=imMPe+Ssz`M10KZ~y1+?%%zCyL4;DnvqX&WoNot`!p3Yk4^P^5k&U@s^ASR_#Qv
zfUHX^W4?=e`s<$Y!|y}SGZc^Aae49N)7w%H?Z~ys;N@YuO_uEOwjYy&xk>wmgKf`N
zCm8{6eW`8RYtyZoB%-RA-zYJ`}7KTGC_
zFqL{vDqXCettx1*HlHR6QaO2aXm;@pNi2S4o`SKy>_?VT;qjxY)z&X$s^@qXlBJ)h
zEoK``!1A*~Izp;)EPky7P)+))6|GhGLzeO#LFgqKSF~)Y5O4oywm?}}{nJg)3!&0C
zb;G`VDj^j2e#-SL4qYzG&k0p74}bn;*(c2C&vHfF#G5k}Cq6WMzLN|}557x;XskHh
zK!mMSQqQ`DRAn1|SSei@56ZI)mya91SL)kFv#45?3CkZLf2SUlY8b5DynFr6TH!nK
z=Z%3qqY@HN`nS59o)|X74jPsyiyUs`&@M{qfAy?Ap;z)a%RQ*q&3vl0C}{P(kI`US
zp5^cCfLzl*n5-sK!E++V8+x0)-x~{fPcUBgb_?VNt+|DJ8ICUrNL%mPIh2^Mb58f`
zF0!}bGS`TTSW7+!i?7|tw=R-{MGe)_K?6Q(Uxw=KMRHyxe$ia@-s$cdHglwHKn%@a;Wf2xNa}*B>8)w{iLDDQGeV>_q(_?K%S`{F6Q!pxA*e1
zZXXKw-19)o!fTR!vYMhXO_$$y4;zPn2f`&T)>jXUTq`A2KAnsUFVnep41&-3{y)ffe4rl2+DLPMZRw-&=aY#HKlg9#-Ol34di`9~je%A3jd9owug#k>!wFk&7suP{8ZQm}z5npoqr?A=
zpGP|JFG`D~DnIEj{IgSaEc?%j7_OTZd9FU-<2GCTD0ntVWfRpU#~MMZ(TF@gYS5D#
z&tHIKFI?iOnVP!(oH-#mloFr9F*E{4p160LfM_!^N|0K660{apL5t4e@!
z+DAUFAG8Es^(n@_8Hp1a|3yUW=ZJi{`!kd&R{Zc$Dv5tHZ!f5o*`4WCNeB#-&4<4EF&lJ^D5!9s|4ofWrE@+YTuC)n-0A3vQ?&0=
z${B5OPHqeNdSDmDze)`_=h}=Sib0TaM1zx$*{PD-OF?Sa)Za?*is+a6Ca^b4#&RIj%PD&FadDYJoyKn#
z*ZJg!Pq*_k>ePe+oMM&>6IVrD%nxOQhR+Xe-GSUxvHtysbzS3h)qqmH<)m9*mc2@KzE_ApBb4bLsb2$>2@Q1qFd%KI
zpKo+r@C0wG>*e*)o3GN8eOVIgh7m3T24>Zx#MU{?OKDInGxy%(<@Ws
zT>i(;Y+X*9iU`=fJtf4rwAAEhA@CluTzux`z3}k-GW~h+<;;}ZA<>^pJ+f*qH{U$B
z7L@YR>x(#~nW(E^z0-lz+j`dWVJ{*~QPDoJ{zSV?PLN+tR%-{dq<#6*w?LOwwWx*v(UFVH=|;Ltz@Sdvvf)84N3h|4`OcI$_nbD21q@`@JI_+
zW<`mX_9X8=xqJW6obK-wga)qc&eQmF(oc(C_-!|sr)ZQOJKle&Eh<%{9>Z%ivmpJg
z)WJOFTV4{qN9LEOi`#_-FM|wkg)IbH
zk7FM`?=w&k;#DuY1+T{SnNH*&;+jZuMrB0|uGN~q+zWRf*LcQ=uKzCEpIFPox}W
z6Xq>7Eq`QyihSqZ)qXjrk*wz5*jE_sP&so7)1{Uv#AmJs5_!b2)2-FbiAoEQRpVZA
zu>2aWj?9YA&Py_VQdo7V1N%=q6bCY2k>^Qmp^b&lJ-_r+GMaWGSx&5_r{^Ai)kCxz
z6^J28umDhNTWhg4mi^1gbI6$Hb~(`!Q}4j*q2<9>-tTI==mp|ZQ3D+G9%np9Y;N&|
zK|2f(dc_i%boQmq($W>`C)Y2KcKx+zXEiW|vrL@mHC0l;VmG2LhiC{)ei)%iM;
z6G;URx83P8`#O(INW8b4^5Vrg?Kr`roa&Bywf`C(tc_lRUN}W8=`(E>;=8zJjee2Rh-g37t!~Z`(mN?|;*4`1eu#FMaVquX>=r8Kb|eqOS&{uQ^Ek
zY(ajb!>LS2RFuFs6oSD)*68`ZD!#bQL~hgIvlzj5wB%|GUpxU)Fc8_`aK1z;hwQHXy4#D4(f
zHbiI+fLMq^s7%5KqlkGDm(OD%ZUl&|F@FmtMl2*o-QkK8*G43|4`JaKe!dRHi3txf
z7LsZW^iuQkc1%5omN<__`>nVJuo8kC#e>yinMTOZ0RBr@NHy`|z0U&iiPwd6)zw=f
zXR+{3dXfVxxkxqXL?SdD!~cW^Kb?q}CL-3E*Y?@SjVRkaT*hy}`4Z|S@y8ju6B$>2
zW~8~Mu5?FO{Bk>bMnYeL)WhVzw8H-mkha4>JWr$`^VNS5k^4mC90v}hA|56p-qQsd
zv3v!~X+wR)cnqun6{F}8lekP;3PLV1V)$Jz=}ZdEv|gF>lvG6LR>CBzVd#5Q3C$g!
z1`~1pmaESJ&;UA2YzncEHjaEl9Vw;FPNa^--pZn5m)9TsH%%wSo!{mLaMb0
zcGA=GvG9Mma4zcP9Ru~k0`;~|#BZ#K@cX>4;)q!q9O4N}z(WE7kn>Dp1f3?|C!jQ$
z)b>2)=#I`N5xLzdlEgi(I=U{jcn=r;laL&bg`{Bwr#Wz=$5zjhgl1widHigR
zTr=`2O?1B?fvm!9B7zty&`5)&;UVEzh%YCZOijvQ6(gOJHI2ij6Vn??ZWoM{rEDG?
zxBVw>2kPFbJzebAA)+rtoWSr0upw<2!8ro*ipt&B9H*aU>c5jr|0Lx&iYELh&fCW$
zSBWu8&n}WAidr`K-%dhUp{2AESRp`QkPx$gy|+LUnpBsd316sqar+KmRlwtbsw97$
zyZDB(?-m)S8_`FL13
zofwFMoCn-Oa#{ShJW?hY7hg==(4-*$VUVHAcSq>(*}k*haX#LM;tGJZk)Q7QZw9Q3
z2A+4Vwa7$GU<59~_;wAt&E(gc>tJfWKu3I+*cO
zqbmHEX?&hA50B7!c4V~#ab{9y6HWYyak$>=_d&fe->MN2+~}9mNUUxQ>=0p2AZD@r
zflLTBiu9XkIIgeWK;tjM@eOeVi_t;+LQUGb>Pn}P7hA7>pbI|1@?{VbT`3h2C|KqO
ze+w#k4At-=9$}>(^TNLJ+OLKiz4<fwpv
zhz!iNLgK|1-Y1;$N<{&*G(TE(^}711n5KaHVNG#!Nkj_@8U%nPl2Ps3$PECpivt6(
zTR=2mG6TK@2;U-zwJR``t>W#ks*l^~c^eZ4=>klrI=1j;pZp;Di#t=xVB`6_=2~bF}~M6-2&Wrc?K&`gBN(ZAvny)OFrA&87ADX
zC*nsrfBFluYyt7Tx7_)DWDfx9;t`p^5S;n<7$*L_vN58%JnEB1ZG&^Izk$fA5h-GW
zzu!dU3;w?u3FOX2*k36C@g=`04IBv&d_{-P;hDG@VZMR;!Ct=bZ1q1;c}sRzc8MuH
zG}x3m-`l9e<&fuR%h89NpMQEOws-iU{6id=0uca<0$}KnY^*>l2R@Beuj|wr;?5&)w~2j=LU;>6hi`
z`sIJ`pvtj$sF3|csp4UfYcDWF;ISHCe_|bCt@jmPKm`S~!3#9t`LYT8du{w>Y_M
z0D=O_MnP&gg5cdQzDky12kYG9VyhQ|-xvs4?;e@t9%_D1{l6Zsksby0LA+4!uwk#a
zmG4`Ezy&NM9|s=`t=?b@w6b}TD4-;fe;B7{%)0iAz#1mNj%@%$umBza$c4stlL7y4
z_wsqwoZn1DZ>`uL6mcnN@K|MFsgKLQXKzBL-)Q|4Upgb0hK0nl1t;*9OFjZIw1Y8&
zNE?DP%xerRGTAg_7%Ole3v*xqc^CkG49J;FeT
zkk&d{BKW#Y>osbyO?dEm&?ZS~@?cGdy~D9BtWY}T{ABNKO&k_xgR}8`Q3LQfl$@7e)ueb1R2uyA~eHr<5E8eXBswdw*hmRISqT+qkwjU^U{A_L#EpG7iBDys?;l@$glUPJ
zMwICtPzDUe0(J2MEPT`+tyn7XlVo(Y?Jq$VQ6Lcomc{{iXaFrHG@B@J>NR|clF=UezSWUI&(~TlnWmT4@TkEMF^lo_S>P2>~+Mdcz??LBs$!5
z5aDiv{Da5ts3XhQQICd1{y8F+*pJ9q9w823X8?2#$5%@f{BO6)5%@h){(DTvwQCH>
ze^|siF^es|cs*A%_;KF9`V#wySo2M!lFfo8??$ZrhC^kEg()d$gMYULu~*J3jRy$R
z_!>6uSo<6D>ero@`vuqiHSUSj31_v^__g6cFdHDi0D0jKQd$>JvS|Ey@kBX^T@2Wa
z$fL~W2ZpTv%3b_d`X~ws|Ab<9$bRS2bK{NRZ+CZ`zE6cy`7UwMg0nc^V@F^HcmRyS
z6F&$yzM&DF@K>_(ub?h_KU?57o=2L~$HNAmVZs`S0!n-9faq@@ajCp;S=&Ea+>
ziaeA4_~qoudfRfl9EHHihh7RM3AQ8Vht4!wUw*T6yr=v!=IN!g_nzB8zrxW@6GMZy
z9I_`U{P5g?&Ym2f_C$!Hy^_YsJCAa0GWefe)scGwMKSsxtz#rnAT(`V_~^`X=3`Ob7ch{6U&@A8L>mn!f78s%r)Xq|^hg=@Q}lK9Zm9GJa^
zJh?QcSH4enrT5s7T=H&yz1+2#&AR%5rK`hFQ`DYNG1-JA7Xe}CKX&Pse?xWkqZ%7}
zB`!o2T{2R7b#~}(;;A?C#5oX$Knred_*`=%S2OxWinNcO{7Q``%))(+b>gLMZ9c-{
z)8G6^3v5?ShNaoXtnVlOuH>_neAm&6sIaC`hg)ZxLg?HS5lBaRDUZxq+M_0E7uDM_
z{T)HYR&4-301t{oq}WGwT#&wGyY%#~@W(L+xi+7%wG$(OyOdsb;LS!k-Et!3j$xYP
zcRBeC1L4W3B7=C1TdemG=a0!<1lk!#ryz0IJ)4WB(9Z_$ZGZo!JiHz6>1SiEUga2A
z7S-7hEW3H?ho)D_T2aDNi!aR$gGseswQwzA*WR)Smp3&euof#79ieq!Y?LgS79n%v
z`H1}kEgw%p3Q%b!CC}|t$_1%g+1sjjMO?cDCa%1y8h4lS&<@KNAJ7e^7!Jk4m*3LH
zlT>a!Pf`&xuK95oV(%#A2eY6>Ln=ipF<+198q+ev`
zW=e&NgA@YQ6kP5u6yeHq9`TgEO;nk1PB(-ZU3nhnw_*1|LeCHdL
zTru-A#|fLWsQV??Mx*{}}V!j+y_*+4$n`}+LR@%pq|ZjPyI
z^SM`Pit+TK<1YA6+RUJWm_rDY#|4!g(PSfCG;++0H7`iubU=}8G|-dH%d(V!_i3fQq-a(GpY+Ejym`xiI8r$1^us92s(AB
zLh#Gd18rv%*{QCmZl>PmLaS5%f#zU?BZ3l{u!!(#*$*b8IE{1>kF83mAesmg=cH;TT{yyb%RZ9GEs4z^>SM)WNj7>
z;xgkemY4_t84)32CX1!N2~&W7l0B(_B7M-TaOP`g%P*L%0HebTKv4ooA9hl@C2-2c
z;KlfjTy~uGW;fRookeqa111-qVL8rzrZ0vENEM;ecm$b1W9<5|kJM1Bt;c6o7OI3S
zILta2AXOU+(vGoGa_0lxUc@1df_F7&Kg{ytH$Woi(Iky0y2$96F7!tR1;4g=Dq^h)
zb^2MC=7HE2FB42}DZ6c!o#K^_1xs&L-mzHm%S~xo6$@$wDPa0i!2}MZ1Ji4^mX9o3
zNtb~N7FtYg3Wl`C!=$l9;015**2IZZzcwH~_v{@>K8o&3GL9B!ZE4XV)+zZt8@6As
zyhlmcK3!c5w|G7;Xox8VlCV9x)8O1O*`?B4a0Jo_XWHkPB08D~QTW{LePhSS=!<4e
zh7xx)Hx{!1KaaOHYU{{Lnpu=!-+XAlrbMWhZYKY
z^$jj33E0eZXg{E{BS_IbJMYU64<^93Amb24(8n!R*lhVRG`R^LK_E#}i?E3T8NK}H
z(Op5y42mjzLD-|XJ8Zu%!}W8?U3rp_UF$Z=9XNYdD80A9j+y{HjR>*m5)$)Y0hmSc
zIJ>2e^feWc?2QgF>q}&fLLE#ZQ>YD%{)ae^myc#g`$FNDWmh#c&;vxOcO2>5Pm|ch
zK7p?f81F4TUMzcL+<$hs*$)+_w!kkf&xm7QQQ7A;C?K}^MkY>3<}$1y3OG|PYQs$A
zm~9{<-8?+q6FpWc>qt2oeo64^+4v>#pDT`oh~O~=h!7r!bl1(=N>;agbb^}j$yGfj
zO7RYigl^2=%ydv9K`&QGpHVDLvbb^v5V@zu!F?04IBi>%vX$9PW@Kqw3m7)6AkK{hyYFrISR
zL~H^LZ-=!-;dqSDB-g}7k!V_CX-2KR|OU=DrWNs5RRU3+CtZKLePQ1!{=NR)krx|q-mtEK{V%8)qeN;dVloBd0aj5K4J>(j!F$D`9lcN5>
zDAjdjoG}55Z~!0^K&~W@^GdoeL41Uk`{=C1M@8_t#OHzonl8J%Q80ezxA%W+QtGTI
zp{R5{49SSbVN
z==XAiSUM$+2DJy0H?JO+-DP0r-k%g019FOC~Uf0qCw}<
z$y)%*LFE}_suH<_Hdsj!bt6KEDOv!CV3nF@b=jcLO`HXcEnOK4qa3WNPX(Yo^U#SO
z(8=VJWD~@~S%@E=M_&zWgx4;dI)0U4;`3)vSYYU_BduQ;VvS9$9s^inc_TN-#`1cj
zq5m0-3JhzoZz&uw6Cf1@CamycELCjvGSIi1lBI2bDm`k|di=sg)#<({V4j4;6QP{S
z)AKsKhp5~^C0J1`-+vg(tDclgY_b4;BI`XPF1;$V)aSOVa#Z6ZmR3dVENSMEd4^0)?+jiBzk^2E@R8I*5NNNN}m
zcq8Q;V00VP=SMLBYoP0=s$s15#FUly(=c3R?VP%D@44l=CNM^@)5H6Hi-I|^avE?
zaufxZJ~R^BKip0^J7{PBl=S#Yx-JOG$#hFCb<0u9zvyh_+nR2IAsGYG2yF83t!C~@
zO`&TK<5UD{WVi7KEjN@dr9cNLY#hBr8;4h)dAQb_eCxKF@bO#qlvHc7Gv0%5>KFo_
zN@_$2;ZuwGb+sZUPF!_|N{^Ut(odJApIHHdsYEnNc6-M3`nh*k8I+3z2>RP_)40b2
zTN}^S`(lcaqn@cy>HyFLsKVkoO(;)0Mmg(cV{J+G_pbAZnlcI@hu630i;R3ubgcLT
zT`q@s)stM{Y5oA!8k^kKms9FI{Tegb6T48`Do7XutW^qvi5z
zMWoVGJTkGv-V>B`KTTl;4nzTz9eI0ZHRwSW!MCX=3*T1VE8O`(KC_X+U2saZ!a?$#
z-qoLZe}g4)zvn~Kr{M>Cl
znIxvyjjHlX4Uq<6EA0Lh6eTH9!xzV+hX&WdD6w>p?IN*kWu2Ts{+OZ}Qzl3&F~t>4
zj&h{Tgibqc&&&3$@Ja;Gs|D=MEZBma
zp5j%+r0Q*?s<_aMUFl)RZrxB?Vk(El|^w>
z+DCaJoRB65&)@qxC_Oh{1zVJxV=RW48aMH%m;ev7HQ9@4?Ukn@y5}3m$bMAP_BGxJ
z7)8apW%SmaSFg@YuZYFc-h`rgDThgpj)O^r#h!EaeXj&tw;&OTJW_O!76I(eCdad&
zZvp17z6Kco3pl#ndpy%Q_y?uf`&?DhIU!$no-s96))Feq-Q8A&vM?p?8KuC6VPD-CMOFCj_h&vudNuW^zKyq#4V;5i)6yJD;<0I|f
z%)=t-<~Z%hRdOU7v+pcd*E}`CZp{9c3Gw=mH4CvX1;eo*9V#heLT5G=-cRuA{Qx1T
zfe=iuyAMqIwrXx*<eMIn@?6y3!Z%l(?1jXNg3f#4KM&=y&`?E@mZl2s(U->_z7>
z1f;xj10Xh1T>rd{MpK65&&9CF1U1rO+{cyekoiVU9-%J{C`zmv`5cNzEC=kxB6s~2
z&inSXL_DVy!6~~_B>EyVR2w8X<@#fsoJ1`ow+mK63@eBg{=zGVgT5v%w7zX7)&5Gf4*{;*oygfhZJ$WUNjz0@iGB_J16RcgTxT;
z3kLIjj7N-$4M^FLLHAO4(15p_KnprL&HacGl{Ee1d1_BRvzNbz4|+GqIoblk7%F}+R`PCG;dfK33zv^2$fJWH;T%6k;i)*4h0zLcCoj2RUOyU~aJLZF1v
zAdNSJ#wKFMBQKNgYNZ87`F6eo6H*Ffr~pxyc+Ri%)}1NV&XY;a|4Nr5Rv_;G7y6xb
zY5-CU5CK3Qyhh;N{8f!MT5-yo5h~HX2-Z^r@6+|}p8Q8!h%2L`jd55$RGNAz$Q(t!
z$EDQjyc(fxp$e}ww)`bN5_|Wj=E0%KG|t~Mf87I^l4^~1{)OFFS7=FL2c{nn7bId4
z&ncc?qCVq}rZPAD&=4nPGL8;$MT3MKi~co%>^sr}QW=}*Jmcsup^FiZ0LUgkeryOB
zzw$g15B*N`UIc$DX8(AQnVddl+E4pWaE@%nN!gbN;Ta@#K$^c=wHBCq1H}EgYP^Bz
zOyif(6J_Pzenb{lJ=GMlsbG`DZ9LPpvZ=_TK|e`~s(rsxN4jhKBwYOo!Rp4oxbN!9
zmdc6j-|J$cA%b^0?r;N_o79>)mhs(!mYxhC+#qtM|M8;NXpMb7r&R2lh8xB-yvr?u
zkF-+!JiOLL<_ngIOA~b04qaRxlwz0e^M81%%D$@`wbtgo6r3pgi0d8CVl;?oO`Bca
z*(j5SZEKvk{N{=9`dZR~0E
zH!2R9LUiT|mY9X=(1!-=J_@d>Sdoe3$lD8(H+rYey?%I$)8*9=hGs^A(RvBL#x#ri
zOqblhPwBpGHadQ)R4=nCU9&G@)?$b!HbYF(1qT4iNOw3YvoHZjQnJAK^;x3>r&Qdc5Y-7HiEnsnvs8VLWPd0MssS^sUkK55vl%
zV!oyGfqIukh7Om810mA%kas8OxIMcv+{?#5{BP@yQuA}H(-V3@@Cs(1c5a#w`EXCO
z{_xQ)R$5@ed$GR2`*U!KpeIAFl1(=U4F5?UJ?JGrVfLGe4lj8puIi?}LPxI^cjPbK
zF`jl?fP#6NI1X-KmSVlmU*mmw*fH+P)skxkiLMZp&&{X59nrttd{9DKkOZ~8nixzF
zk7E>%-2EnDb<;VEr5xSJ3)C@7y=SCcy?mOLy>x+#{-7CmHKZZzSksk%GxrUPi%uSq
ztSjJyeNwI*FsKgi=v6zcDtbGcH56W9G46Bv{pelG`!hFPKX(sXtR=<_m~`~Me=vSq
zY)O{5$?(*U+GG96*7u5v!a>VQPn|Gz8u5NqVf@AX+qrktg>;G18GnVN>$WZLPJD@6
zbkVpOX9Wg=O;8=EMAYJd(Tv+=53{A@nc)+9gCvBZRi9O_c*e@;keO61|90c8bQzyP
zhJWv%QEn3f2MWXL<>+~b%O_g=lpgdSMGYc+-krSqD%th4gC;(fo#l2|MrjwA(|%t6
z;$^}=POonA9oDu59@btM0ZxX52WUrY<8c1fam@!An7Fg9QXccAgW6?CRj^N
zhfqw;PLy21GE(+&=a0_J=Q@u6Up!?3VStoF77AkB7_z!Xex_R~>4xu@KE}{QUR;fh
z;<{;{sZTUTH+x=dc7^OWDxv>AB@g@TKI;U3LEcr{Pk4S4B3v&Y9^9^g2*TMK4^`&h
zmexu7?~C7$3W%ZB6Wc3qD`h2)b|M3sF|cWUha>G0_Qf1~i40>bES)IZ`i%}zP}OpM3;~%F^z&MiG}1r%-Av;#J($fVz)~tmt5WrG_BRNUU;P}V-^M@?AY%+Ns
z%h{ws3=;7vUJdw=u!UB7n3QrGQHT~W2L}cvS?wXdGvcig|6U{l}%vv
z7^Dv1N;V5rl-`+o>lk2w{$#}!Q+gY=>M#(0pd|WNd`i1`6;Vk_p!!|aZhB+fCO+n+Nhjuo8LJR8}&u&zVpUema
zi_hVyPaY~ZXtv)+s4uv+r`k5UJQdBh?X7A>_qs9eK5*I$p%#)H-`A{g0k9&x?(-5xb-YMvJ;;hr$Nrc8F1q&!q@ii6!!w
zWA!fGx=6*sK8vm>h)xnPQ-@|H(aokruVz*M%QaQRe|>8ESChtdrc@A%`worL$Z~5O
z;VF8bxy&vHmK7=c9%ip3{8T#FIY&ZD;f(B{#O&rEapFZ+eT73c@mxwNvEmoX;|&
z{Z#!!2TiQbz5FHbhDVcX|Lr;3Pl~>_4
zmTcatApIH3l`6gU*9~{FWz@Ej8mN#1#zLfv_
zEy0>+4{3cc2;z|k<`WFdE8zm+5wmap?lwR1n9@5MPFvI#-XxpVD@e5v!I(&0_(g1#
zFXrMKOIEbEy{J48wqd0qT8vDdx;UXdM4RVH9Sha!LYya(4hQ6IGwt~b}Nym=jQY4|Sk1}a6QT@LbnTbVb*rJVV$0;yhb
zm+O;H)uYJ^My#ApPtPxn^z0J9tOk~{^@BV5E|1AOz0eO6BEc|pXhSKl0V{f<(wj1&
zn~9hx&Zp{>c8I^^m{<6o63(fQP;Gg@qkJk_H(0t64D}r2FCy|gCRGO^qpt;1l|^e#
zBpvEO+ew`e=L_1+{C*L7;lGbZXsvQZGQ$A!G{-)}#WqZ4K@B3EZH3A9(LJ0quRiCf
zBn#RHFOHw7RG+Ne>q6bj>*76qet=}`2{zmS>A+GY*(mAy6Z#>fw|KGz-Nw8$M=Qk|
z&t(mOW=u}H%c?W+kCmt1}E%T10epi
zT|S;Pw5T2mtT=<)9ZNN?AsyZ5GJx4g5mRb&-X0y3{w^l_Ur*&E%0b!)L$u?FdfC-j
zoq0HygN1GF!4XK@Sy)fpvI5lI=iwHIfkvgC51m8sNam
z0J$cKiR1i@&80;HU1l&jc)EgFU=CHeGJ0f&t_(IRbw5gw(F?a(v_PbG_XzI*jcj?1
z2M9kBy{u})@vVK5&%v4>fM^4x^cN!ej9~E
zD=9#Zyn=sZb3d?m{y%w)(h<6OjMJx^#f{;!IKf_YIV?SYSdFLiA*VoNrL(r#S?i6L
zR5nnWYJK&w%@NUAt8hMxnl6)Yl95F!y#3bqz#+?4ze2#hXxJw+Ith#F#E+1}B3z>m
z{)#99oBpuY!KTVGaG-W6=nPSwhom3UWrHsA6h9V>CO^BJDY-kNRCLB-z~+3rGEc9v
z;?SoY(KO=_u(qcaSPdsA*ohScU;dS&Mg)rg;3rC7@HcwnuRsWpoeMDY4bqY9Guf@dx;`gx3~Z{F-LqkZ#1fZGh{%eLPlT=;GreVBr5xEGAH{bWv|Gy%
zfoM@sJ~fMfjB^D$;Kq=KJwkatyTR;_XYlAB$QI_UV1Z9=#}>dTN36)+IF9WYy)mj7w{mSrpi4
z%vw=v_N8v2EH?G>@|||2o~I~#em)+-7ogZwAf`Rl(36xwQ@y~fyxkdaW~NaeZ!K(_
zi);c-rk$|BPiZy-r7)>XLC7`v?$mWDZ}}RKMh((vuDY$d>-q_6_DoTdqrwc3T5g3A
z6*~yUWML8*+*2%-g`>2!XqoQJ$6hKi^
zyQ)hYA1MVRVHu=(VNs!`9u-M@w@g=KPeg*2r)`DuKvX(V<~sWA1eUZBNM%y?6Mg
zm1KRYVK)DvJ(3GQ&$Kq@KKsI{nz2zK9GnKyW`Y;u&Y1+-9Hf0#87s49nA13}aOk0;
zHmB2Q31_fgT4YNGEf^4PNfOm0MN`Ae)dqi-?6o6U29nk_wZ4Ky7W5IDu}8frR??zk
z`Hj%xU!591a3EVI9~-1+k@g-d=OzAm&~Dl?Tt}zKPNC`HQ48BMn8SYPOIc@6A6CgV
zp5az1s&(+#0#X?`Frh(f{xi{dsb3T9!wb13DDWl$GqnI`V^m
z^5)N38vr}u4PBNTlI0-QUr%d(>wT5%!vK|sU~3hiKpOCB-_C=R=B?IBoY9ABotj!*
z2KXr@C;K=z?5jC2L@o{TR2UlTcE(3Zry@5_=!;paO@xcuvf$OJDX;)u@$P&P51GXX$MNG
zSs&9&m2+eQsKi5#T}IS@@q0f{zdCYLobEZ=`Ko9r&@S!c91^tqatx1Eci*
z+?W8RsL-PR+vI+irc+u@6V=aW>Sl@+CT)TFqsPobZ2LtYx(($b_*O^O!^YSt>}L<2
zRElG;h1)2)W4y*I;&3GZWCMq#2D5f-tjEFrn9et9HlebcGQVUv_m<{>6$DM>5lmH|
zNq0Oc;Pid_s;FD@gSNQ1NMVSk=r-zKvTcNEr)+2jYD^trXK#O>D`QYiU;jKLe4M
zZA1<4ZP}Q3f}f{Yq0{*JA5!)(6qgG{AAHCzMGLoG;%|pPvy6LYX$ut?nK9o5D;-x>
zpCW=RnB}`+D{lRk16@W0kkrmQ_$KKb3F)gC&PWsq@Z}x<@l%fb>{uWLPY*T`4YH4~
z`fZ=8$wXn!q%#(}ZTjLtDmDN$ilY
z1--?H7dQW~^AS0sR!V))naU?whRfyF-RYfArL=
zcP-}wNA4Wf%&pi%ccaC-ZJJjKuJT>5Dv!>GoMhS*=z4_CkW;E938^+D
zMOun<+|T#-cwB$Lb>ENszOL*2dcR)JtIL}CNfdi}XM6L9`Hy?w{v^dZJ+tye0>z98
zcREtJ9v#jgg$^yr9zysHp@Uyf9VhDNo=Eg8?900ZF2YdTF$B3T>*OQ$1;3Gj;iDdt
zVC8O*bi*_uoO^wV%p`4{x3Y)heXA=ghmIVm~ieG%pQ0?B}#&@9o-3&tI>G18uoyY7Zu
zy#C)p-;gBlM)s$l{@~tAVAEF1kT9H!WoJzRSzSF%ot?i9y<4mdxn@PoBZ9hZJ@Z>wi3`@#|Lrny#q>iST%Bd{6(IHK!!0@%$9)Getwfw^4LifOl|4f!;u2^
zyXSm~zro-;P8Q6?Q_0{cD$|J{0Q?ScU9`U%!VkV)EKMOOYiB>kzdkjR>i_#*_RMdo
zzb2L+4h@Qpxd^#GF0RwbAI5Y6C3Aq`aGRewBl2=rx>yZn%=wtEKdDZ*Q5M0|6|~
zW5U*l4$NoaLbP$6O5^|Cj3_b<>=hI0W=lbb4I
zn~T0S21k_-1H?}P_)_Y7(q`Ev%s$kcgIC|2ctZJ-e!^QBpR@Al
zXvM{Y-cz$86530B3A_LP-XC{q9LN{h_h)|C3UVluCnQ#dIh~p)k~G_Wt*Uce1tnmt
zJbCxrsRvO*fCmer6OuO*IZgr+rd8_>;w
z8+JZbYf30tIfTcryA{m>fItw6&Nx>;kRi76=&aMZI)e41xwf%h-^8RZxP|U-I~UV_
zevy2C{C;R-`tR1Ku5Z81eyvRX{e$LzEl)n=e%wNqV{5721XPLc9t9h#OI&=uE}t^2
z8EKZvjfifo$g(cbO}_hlty}_bj4yHewH($+?oZJyJ;1JM#W41?zNr6sTkaqmgXg7y
zh3wj!RGUlW3S+cxP6-xu-g;UXrG0mPaSRibe(`WJm0G%a@=oHwE^?$V;uHn?{DZ`!pY!+1Kh5mP|Ok~
z!nRZ~lFbD1tJ{&PNqA!&0QfvvUva(lWLO<>5HNBf!f8~k@pDe(&L!?x+;Oi3*0Jch
zllQU?DndWp@38cvzCU8shI%|fJip~$bUl@;5!V>@tTwdv1WHdy=->d(wkmIqpw@`b
zexR!?TpJQrABMiNOaVtutYQlj|EgW8?r?u!qQ6YH?V0f`y4-kvEXZ(P`XSG3qi_CS
zL|EfVWofXGd&iJlE6G{0VmW_K1ajEn!UQf02xT-C9q~xncvoWi0CGA-^3d0oV(Y1n
zw`OmNwo;jMFg3KhVjmcx4>z9>GD8gH{ug8`sMZiB;gzg++o*!uJSKDKY-bn1OmZ#r
z7nLg)z1j4nez39j^aW2R>DD4SZxV%aPl?O~iRBrO(0y63@hTN#6h|m%;)>d(%zZ1X
zTvC6NeYqaHiys@WBPlvJp>fIh!H(ulzgLj=EeF3nGm|m8GW*BG>-yZhPvoWKJ)aK^
zaej_D!unmhTnX0GT8Lg6li$maZZNH;o!AJ>qrrtpLsg#YS36qHkMg?n>Q177i))Dk
zJLA}-f5P)!Z^KmP&9X-dC#)Rj(KaGyI!zpHSobUTmWw3~Q|X$@Xa-flZz4-FNbX*F
zVNRQ#V5P2nN8TMO?`1P*aZ6S5eB={tjx^?Q*N{pOYZ&Fl9fHeJs9<&WIZ+Zp
zw4VvJZw-=k%X+KrR9@iZT`rs5LgOq23i}iX3NcXj&g@r>lWlr_$XgPa^jBqj-!&B<
zW(BX>o)E`h9Nkx@AinxWWsxD-Qum-a()$@(ktsz?nHbN(j5TuSw%cZsd<-p^L_`F!
zvyd2XJecbyNS+@_QEYOsoZdD*shlMg3>ZDo@x0`GvW=3yEZPIEI{xJ+?R-dx^1Mr|
zL(!?}ynt1K!{@1RtxfG@L8vmziyR${(IYJfikELF4g!eVSg-+r}4|u2#T%1yE
z|Mni~{8>x6A@S*npAU|^(nNXK+uq7b5$9+|Io(C>P(>lAf{n7@*Zwez>+-y;02Pa%
z@}rH{A$&D>Au^$uR)tKi_*1^oqX#oCRzNU%b7x#`qi?;fFb~!sn{_}8e4K*iw<Bjo
zs7Y49bQFk)?j)zaZK<;W+(FCggE8MpG|TVQnz;NG$tZr?LwEITcxT!Muid3%&VD*0
zc<#{Uztwm4^ETo@UXrsMPZVO>Q@(71f(nLqTn>+=q2VXd@#wqC#zamwSR4l{#^oKd
z{N!<9>tfpF^tsXcnZ5vLc@uZ^WmP%qF&
zj~#gNdp`cM74}SqEE=`fZ`XA^eWR(zcjE&!;nl+J0MmaXrKBX+8`;Zc$-PSQcGdn9
zCVMW%%GNyTLn03GOWjwC^80RhwuKCid%>*mc%UM8q#1tbYpPhN*<$^;X@66ZY3o5$
z?^zb;)Say@#;zmMpO-mpID&Glfpbz_IFgr-7ARF-fwF+{w1KlTr8ZoG*a6*px7
zfl%h;+5FE<_w70Kq0pXm2=D&svzhf-Rm%OW5L0UY=;V`)%DTlVRu
zY1RgcuEjkId|o&Yw
z6flATMh}Vi0xNGt{fO5v?VPq9R=`97HOJV9yYFQYZe9kiMsC+WEjvdH4=bwb)X%Sf
zC#&q}Z^{E!XpO*gECxhQ^LZWqpubx#d9lhHR`(v(QVB?h)6DQ6agy
zN49?gKdlikrlm54fl~fd32_2y8VAqE!P`lKQ*3xXo8N!}i }9m$6vkjkW3
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