Compare commits

..
557 Commits
Author SHA1 Message Date
Sojan bbf74f218f Merge branch 'release/1.14.3' 2021-03-27 18:45:38 +05:30
Sojan 33ca4e0e80 Bump version to 1.14.3 2021-03-27 18:44:57 +05:30
Pranav Raj SandGitHub 6a55960d4a fix: Revert quoted text styles (#2003) 2021-03-27 13:54:50 +05:30
Pranav Raj SandGitHub 8285f5df15 fix: Handle rendering HTML only email in UI (#1987) 2021-03-27 13:29:04 +05:30
Nithin David ThomasandGitHub 8612f307b3 Chore: Update widget offline message (#2001) 2021-03-27 13:08:09 +05:30
Sojan JoseandGitHub c453455ad1 fix: Handle application errors in Sentry (#1982)
- Handle notification errors for attachment messages
- Fix empty identifiers being passed
- Fix 404 when invalid source id
- Handle webhook exceptions
2021-03-27 12:27:48 +05:30
Sojan JoseandGitHub 9903e47896 chore: update rails to 6.0.3.6 (#1998) 2021-03-27 10:52:14 +05:30
Sivin VargheseandGitHub a246989551 Enhancement: button component (#1932) 2021-03-26 20:20:20 +05:30
Muhsin KelothandGitHub ff69ef7317 Enhancement: Sort labels (#1995) 2021-03-26 04:50:38 -07:00
Sojan a0cd1f8bcc Merge branch 'release/1.14.2' 2021-03-23 01:20:34 +05:30
Sojan 5dfc4f35a6 Bump version to 1.14.2 2021-03-23 01:20:03 +05:30
Nithin David ThomasandGitHub 43b5a435ec Fix: Add check for id on update conversation (#1966) 2021-03-22 20:24:51 +05:30
Sojan 818f45916e Merge branch 'release/1.14.1' 2021-03-21 01:46:59 +05:30
Sojan b94e87584b Bump version to 1.14.1 2021-03-21 01:45:13 +05:30
Siddharth RameshandGitHub 763d8d37df Fix error messages during login for non-verified users (#1945) 2021-03-20 17:44:58 +05:30
Nithin David ThomasandGitHub 3043ee5058 Fix: Hide prechat for sessions inititated with setUser (#1914) 2021-03-20 17:44:20 +05:30
Nithin David ThomasandGitHub 484c32fae3 Fix: sidebar filters not applying bug for chatlist (#1938) 2021-03-20 17:42:29 +05:30
Nithin David ThomasandGitHub 4657e5c713 Fix: Refactors error prone checks (#1947) 2021-03-20 17:12:36 +05:30
Sivin VargheseandGitHub e289106c5b Chore: Hover color for status dropdown (#1906) 2021-03-20 13:08:56 +05:30
Nithin David ThomasandGitHub 6afa1fb556 Fix: Error when assigns a conversation to user (#1926) 2021-03-19 12:55:05 +05:30
Pranav Raj SandGitHub 54d578676b fix: Use team conversationURL in team section (#1921)
Fixes: #1917
2021-03-16 19:44:50 +05:30
Sojan JoseandGitHub e44e9fc025 chore: Fix SMTP mailer config defaults (#1923) 2021-03-16 19:40:49 +05:30
Sojan fe8fc570f6 Merge branch 'release/1.14.0' 2021-03-16 00:12:57 +05:30
Sojan 000f17c2dd Bump version to 1.14.0 2021-03-16 00:12:19 +05:30
Sojan JoseandGitHub 866de4ae2d chore: New translation updates 2021-03-16 00:00:53 +05:30
Muhsin KelothandGitHub 7d5493ac78 chore: enable close button in react-native widget (#1910) 2021-03-15 22:40:26 +05:30
Sojan JoseandGitHub b6f4006c15 Chore: Migration to enable email channel (#1913)
fixes: #1877
2021-03-15 19:15:48 +05:30
3fd398879e Fix: conversation list user name overflow (#1912)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2021-03-15 18:38:37 +05:30
Sivin VargheseandGitHub 36f086c5cb feat: Redesigned search UI (#1845) 2021-03-15 18:38:05 +05:30
Nithin David ThomasandGitHub c99c63cd79 Feat: Assign conversations to teams. (#1849) 2021-03-15 18:37:03 +05:30
Nithin David ThomasandGitHub 941d4219f0 feat: Set up store for teams (#1689) 2021-03-15 18:35:56 +05:30
Sojan JoseandGitHub cadb246eaa chore: fix empty user_name. & password (#1907) 2021-03-14 15:39:47 +05:30
Sivin VargheseandGitHub efcf10c00f chore: Added hover styles (#1905) 2021-03-14 14:10:16 +05:30
33b73451b7 Fix: Update offline message in widget by availability (#1879)
Feat: Display out of office message based on business hours

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2021-03-13 14:06:25 +05:30
Nithin David ThomasandGitHub 2a28e05a77 Fix: Make pre-chat message minimum length to 1 (#1898) 2021-03-13 11:46:08 +05:30
6c87001a0e Feat: Show working hours on widget (#1823)
Feat: Display out of office message based on business hours

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2021-03-13 11:44:28 +05:30
1d2e1a2823 Feat: business hours settings page (#1812)
Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-03-13 11:42:51 +05:30
Sojan JoseandGitHub dbf515ab5a chore: Make SMTP environment variables configurable (#1868)
fixes: #1647
2021-03-12 15:37:06 +05:30
Sojan JoseandGitHub 42e83de5b0 feat: Activity messages for team assignments (#1893)
- assignment messages when the conversation team is changed
- change assignee based on team
- move round-robin and assignee logic to concerns
2021-03-12 15:13:58 +05:30
Nithin David ThomasandGitHub 38d1b0eae3 Chore: Reply panel emoji button size fixes (#1896) 2021-03-11 21:48:52 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
22fecf0d84 chore: Bump elliptic from 6.5.3 to 6.5.4 (#1884)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 18:44:51 +05:30
Sivin VargheseandGitHub cdd8d85815 Fix: Conversation timestamp and thumbnail position issue (#1885) 2021-03-10 10:33:45 +05:30
Sivin VargheseandGitHub 1c7e5df91a Enhancement: Conversation item redesign (#1857)
* Rearrange the inboxes label in conversations.
2021-03-09 19:52:14 +05:30
Sivin VargheseandGitHub 94159ca9df Fix: Canned responses table column width breakage (#1881) 2021-03-09 18:37:18 +05:30
Nithin David ThomasandGitHub 0e40f8a10f Fix: emoji box not showing up (#1873) 2021-03-09 15:26:03 +05:30
Nithin David ThomasandGitHub 759ed43745 Chore: Responsive fixes for common screen widths (#1856) 2021-03-08 13:30:33 +05:30
Nithin David ThomasandGitHub d70208a0a8 Fix: apply alert conditions while document is hidden (#1859) 2021-03-08 13:13:13 +05:30
Sojan d5c6e8e8c8 Merge branch 'master' into develop 2021-03-07 20:44:31 +05:30
प्रथमेश SonpatkiandGitHub d692eac260 chore: Add name to the sender email id (#1485) 2021-03-07 20:42:45 +05:30
Muhsin KelothandGitHub d8cb03525f chore: add post message event for sending cookie to rn widget (#1860) 2021-03-05 21:47:38 -08:00
Nithin David ThomasandGitHub 9e8a943ec7 feat: Add audio alert for incoming messages on dashboard (#1738)
Fixes: #1345
2021-03-04 19:24:03 +05:30
Sojan JoseandGitHub ca4a766b82 chore: Enable email channel (#1851) 2021-03-04 13:59:59 +05:30
RicardoandGitHub 6aed01de0c chore: Revised Spanish translation (#1761) 2021-03-03 17:12:22 +05:30
5f250e5b3a chore: Move conversation header above sidebar (#1835)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-03-02 22:44:04 +05:30
Siddharth RameshandGitHub 2120734f67 Chore: Update social icon colors on sidebar (#1846) 2021-03-02 18:27:22 +05:30
89e5f18dfb feat: Update design of Contacts table (#1753)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-03-01 22:28:15 +05:30
Sojan JoseandGitHub 03bc4bf224 fix: Greeting messages not sent when pre-chat form is enabled (#1842) 2021-03-01 10:58:49 +05:30
David PedonezeandGitHub 60b25760fb fix: Resolve pt_BR inboxMgmt SETTINGS locale typo (#1836) 2021-02-28 13:43:38 +05:30
Pranav Raj SandGitHub d6391be4db feat: Update UI for edit contact modal (#1833) 2021-02-27 12:33:12 +05:30
Muhsin KelothandGitHub aab70bf1f1 fix: attachment rendering if the message content is empty in private note (#1831)
Fixes #1830
2021-02-25 22:40:03 +05:30
Pranav Raj SandGitHub 00954aa16f fix: Upgrade browser gem to fix missing push config in Opera (#1828) 2021-02-25 14:03:33 +05:30
82a1ad891d feat: Add a view to assist user while onboarding (#1826)
Co-authored-by: Nithin David <webofnithin@gmail.com>
2021-02-24 11:16:38 +05:30
Sojan JoseandGitHub f424a832f4 fix: Log config env variable typecasting (#1792) 2021-02-23 20:48:15 +05:30
Ankur PatelandGitHub 01ee3d7f8b chore: Removing unused index method from Widget Controller (#1819) 2021-02-23 20:04:49 +05:30
Sojan JoseandGitHub 0e721653e5 feat: Business hour Inbox APIs (#1821)
* feat: Business hour Inbox APIs
2021-02-23 12:11:15 +05:30
Nithin David ThomasandGitHub a3b0de63de Feat: Component for setting business hour availability (#1794)
* Component business hour setting availability
2021-02-22 16:30:58 +05:30
Sivin VargheseandGitHub 4cbdbbe4bd chore: Changes the dropdown ui (#1813)
* Changes the dropdown ui
2021-02-22 10:52:50 +05:30
Nithin David ThomasandGitHub c17380d48a Feat: Create contact from contacts page (#1806)
* Add contact create modal to contacts page

* Test cases

* Review fixes
2021-02-19 20:22:58 +05:30
Sojan 6ba25bae3d Merge branch 'release/1.13.1' 2021-02-19 19:40:45 +05:30
Sojan d1b9e21ea5 Bump version to 1.13.1 2021-02-19 19:39:01 +05:30
Sojan JoseandGitHub 1612f515b0 chore: Fix issues with notification actors (#1807) 2021-02-19 18:35:21 +05:30
Nithin David ThomasandGitHub eec90a1319 chore: Refactor Edit contact modal to separate form (#1805) 2021-02-19 00:10:32 +05:30
Pranav Raj SandGitHub 6bbeb005f5 fix: Remove orphan members from inbox (#1797) 2021-02-18 15:56:54 +05:30
5daf970a87 chore: Generate nginx config using chatwoot installation scripts (#1687)
Co-authored-by: iriseden <iriseden@localhost.localdomain>
Co-authored-by: iriseden <ad.chabod@iriseden.eu>
2021-02-17 20:03:43 +05:30
Sivin VargheseandGitHub e9fb43c61e chore: Changes the mention tag design in the private note. (#1789) 2021-02-17 12:50:26 +05:30
2245233618 fix: the width of time stamp in notification. (#1791)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2021-02-17 12:35:00 +05:30
Sojan ec1ddc06fd Merge branch 'release/1.13.0' 2021-02-16 19:54:24 +05:30
Sojan 6154690c05 Bump version to 1.13.0 2021-02-16 19:52:35 +05:30
850041bc1d fix: Twitter inbox creation error (#1783)
fixes #1708

Co-authored-by: Pranav <pranav@chatwoot.com>
2021-02-16 19:35:10 +05:30
Nithin David ThomasandGitHub ac15f08995 Fix: Warning on new inbox page (#1784) 2021-02-16 19:29:35 +05:30
Pranav Raj SandGitHub ec557205f4 fix: Add validations dynamically for pre-chat form (#1779) 2021-02-16 15:15:37 +05:30
Pranav Raj SandGitHub 1706199a0e feat: Add pre_chat_form_settings in inbox settings page (#1776) 2021-02-16 00:58:57 +05:30
Sojan JoseandGitHub 3ade7d4445 chore: Fix push message tag error (#1768) 2021-02-16 00:15:45 +05:30
Pranav Raj SandGitHub 037ffc7419 feat: Add a pre-chat form on widget (#1769) 2021-02-16 00:14:13 +05:30
Sivin VargheseandGitHub 5f2bf7dfd2 Fix: link address overflow in webhook. (#1775) 2021-02-16 00:10:01 +05:30
Sivin VargheseandGitHub ee3ccbf0c8 fix: Fixes color for file name, file icon in private note. (#1772) 2021-02-15 23:53:52 +05:30
Sivin VargheseandGitHub c1a2f75509 Fix: Color for private note links (#1771) 2021-02-15 18:24:58 +05:30
Pranav Raj SandGitHub 64d7dc5335 fix: Remove teams on account user destroy (#1766) 2021-02-15 13:32:52 +05:30
Siddharth RameshandGitHub 27cf5ecdce chore: Include website_token key in the inboxes API response (#1765)
Many self-hosted instances require this key as a part of QA & maintenance. Since this key is not sensitive its better to send it as a part of the JSON response instead of having to use a regex to get it from the widget_script_tag
2021-02-15 13:08:15 +05:30
+1
Sojan JoseGitHubluiscperSin V (jiiniasu)AlguienSamathis-gavagaiYovan Lutfi Arya (Regerta)vfasoulasmagnusGoudarz Jafari (Goudarz)Pranav Raj S
84560953ea chore: Update translations (#1713)
Co-authored-by: luiscper
Co-authored-by: Sin V (jiiniasu)
Co-authored-by: AlguienSama
Co-authored-by: this-gavagai
Co-authored-by: Yovan Lutfi Arya (Regerta)
Co-authored-by: vfasoulas
Co-authored-by: magnus
Co-authored-by: Goudarz Jafari (Goudarz)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-02-13 15:37:06 +05:30
eaafc45f45 feat: Show teams on sidebar (#1754)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sojan <sojan@pepalo.com>
2021-02-13 14:58:05 +05:30
Sojan JoseandGitHub 8d45849d0c chore: Update notification Message Copy (#1685) 2021-02-12 22:56:12 +05:30
Pranav Raj SandGitHub 5defe648b5 chore: Bump rails to 6.0.3.5 (#1755) 2021-02-12 22:27:02 +05:30
Pranav Raj SandGitHub 9315cb81e8 feat: Use audio tag instead of download file button (#1749) 2021-02-11 17:26:14 +05:30
Pranav Raj SandGitHub d92a6a3078 feat: Show date along with time in messages (#1748) 2021-02-11 12:10:08 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Nithin David ThomasSojan Jose
a880845d2b chore: Bump marked from 1.2.7 to 2.0.0 (#1745)
Bumps [marked](https://github.com/markedjs/marked) from 1.2.7 to 2.0.0.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/release.config.js)
- [Commits](https://github.com/markedjs/marked/compare/v1.2.7...v2.0.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2021-02-10 23:29:04 +05:30
da94e65d20 fixed slack channel builder so that the channel list can have more th… (#1725)
fixed slack channel builder so that the channel list can have more than 100 elements

Co-authored-by: xinruiyang <xinruiyang@deepmap.ai>
2021-02-10 20:22:06 +05:30
1484849cc7 chore: Update method for team members (#1734)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2021-02-09 19:21:31 +05:30
Pranav Raj SandGitHub bf2b56a988 fix: Fix bot message rendering in dashboard (#1743) 2021-02-09 15:19:47 +05:30
Pranav Raj SandGitHub 88fd2c22d3 feat: Update select button styles to match button styles (#1742) 2021-02-08 18:27:20 +05:30
Pranav Raj SandGitHub df0d7262b4 fix: Show push notifications settings except Safari (#1741) 2021-02-08 16:39:15 +05:30
Pranav Raj SandGitHub d4c2a78db6 chore: Add Chatwoot SDK to Chatwoot Dashboard (#1726)
Add Chatwoot SDK to Chatwoot Dashboard
2021-02-08 16:38:35 +05:30
Sojan JoseandGitHub f46c4b5130 chore: Minor Changes to Bot Message APIs (#1739) 2021-02-08 12:50:11 +05:30
933661b22c feat: Save rich content editor state to user.uiSettings (#1736)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2021-02-07 12:54:32 +05:30
Pranav Raj SandGitHub 235e4325bc chore: Add error logging config on the vue package (#1670) 2021-02-06 12:59:19 +05:30
Nithin David ThomasandGitHub 19f7a2eda1 Ui minor fixes (#1735) 2021-02-05 23:24:50 +05:30
Pranav Raj SandGitHub 55982666b0 fix: Use encodeURIComponent in generating mention url (#1733) 2021-02-05 16:10:11 +05:30
Pranav Raj SandGitHub 351403457e fix: Use commonmarker instead of redcarpet (#1732) 2021-02-05 11:24:18 +05:30
Karthik SivadasandGitHub 2012aab1d5 fix: Standardize name validation on agent / profile pages (#1720) 2021-02-04 20:08:46 +05:30
6a614a520b chore: Sets up store for teams settings page (#1727)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-02-04 13:19:59 +05:30
Sojan JoseandGitHub c61edff189 feat: Add bulk imports API for contacts (#1724) 2021-02-03 19:24:51 +05:30
Pranav Raj SandGitHub 7748e0c56e fix: Update flaky notification tests (#1728) 2021-02-03 17:55:27 +05:30
Sojan JoseandGitHub 5d5e75ce9c Chore: Fix Deserialisation Error in Jobs (#1683)
- Ignore Jobs on de-serialization error
- Show empty conversations in chat UI
Fixes: #1480
2021-01-31 13:05:07 +05:30
Sojan JoseandGitHub 0ff81e3b53 feat: Add team assignment & filter APIs (#1712) 2021-01-31 12:40:02 +05:30
Pranav Raj SandGitHub b0563a666e feat: Add support for Clever cloud deployments (#1703) 2021-01-29 17:08:40 +05:30
Sojan JoseandGitHub f9c3b7f2f1 feat: Bulk add team members in Team APIs (#1695) 2021-01-29 12:34:52 +05:30
+9
Sojan JoseGitHubmagnus - NorwegianSina Nouri (sina.nouri) - PersianArnaud Dupont (dupont.arnaud.58) - FrenchIlya Konovalenko (ilyakonovalenko) - Russianlybtt - Chinese Simplifiedarturczyzewski - Polishvfasoulas - GreekThiago Costa Cavalcante (thiagolinocc) - Portuguese, BrazilianYovan Lutfi Arya (Regerta) - Indonesianchinyaev - Russianthis-gavagai - Nepalipetrs - CzechSin V (jiiniasu) - SwedishAmbler (ambler) - KoreanNestor Davalos (nestordavalos) - SpanishGoudarz Jafari (Goudarz) - PersianPranav
bf7915c8a3 chore: Update translations, Add Norwegian(no) (#1675)
Co-authored-by: magnus - Norwegian
Co-authored-by: Sina Nouri (sina.nouri) - Persian
Co-authored-by: Arnaud Dupont (dupont.arnaud.58) - French
Co-authored-by: Ilya Konovalenko (ilyakonovalenko) - Russian
Co-authored-by: lybtt - Chinese Simplified
Co-authored-by: arturczyzewski - Polish
Co-authored-by: vfasoulas - Greek
Co-authored-by: Thiago Costa Cavalcante (thiagolinocc) - Portuguese, Brazilian
Co-authored-by: Yovan Lutfi Arya (Regerta) - Indonesian
Co-authored-by: chinyaev - Russian
Co-authored-by: this-gavagai - Nepali
Co-authored-by: petrs - Czech
Co-authored-by: Sin V (jiiniasu) - Swedish
Co-authored-by: Ambler (ambler) - Korean
Co-authored-by: Nestor Davalos (nestordavalos) - Spanish
Co-authored-by: Goudarz Jafari (Goudarz) - Persian
Co-authored-by: Pranav <pranav@chatwoot.com>
2021-01-28 14:03:52 +05:30
freddiiandGitHub 229fcc18b7 chore: fixed typos in code comments (#1701) 2021-01-28 10:39:37 +05:30
b93388b330 feat: Tag agents in a private note (#1688)
Co-authored-by: Sojan <sojan@pepalo.com>
2021-01-27 00:04:11 +05:30
Pranav Raj SandGitHub b894b13e14 chore: Move docs to docs repository (#1694) 2021-01-26 16:43:45 +05:30
Pranav ecdeedf914 Merge branch 'master' into develop 2021-01-25 19:30:58 +05:30
Pranav dce719b5b1 chore: Release v1.12.2 2021-01-25 19:30:34 +05:30
Pranav f569f3a01e Merge branch 'hotfix/v1.12.2' into develop 2021-01-25 19:18:48 +05:30
Pranav c9285449fc Merge branch 'hotfix/v1.12.2' 2021-01-25 19:18:32 +05:30
Pranav 7878b9fbb9 fix: Use git instead of tarball for prosemirror-schema 2021-01-25 19:17:45 +05:30
c087e75808 feat: notification center (#1612)
Co-authored-by: Pranav <pranav@chatwoot.com>
2021-01-25 00:59:44 +05:30
Pranav Raj SandGitHub e75916d562 chore: Move Canned Responses list to a separate component (#1681) 2021-01-23 14:07:01 +05:30
Sojan JoseandGitHub d64ba1df8b chore: Add seeds for Bot Messages (#1676) 2021-01-22 01:01:02 +05:30
Sojan JoseandGitHub bba296b5c6 chore: update identity verification docs (#1677) 2021-01-21 11:27:34 +05:30
kgdevandGitHub b4a547e0ae fix: Incorrect Scoping in Contact API (#1674) 2021-01-19 19:48:15 +05:30
Pranav Raj SandGitHub 12491fa8d5 feat: Add "Enter to send" option on format mode (#1671) 2021-01-19 19:28:40 +05:30
Sojan 2ff0af3c8d Merge branch 'release/1.12.1' into master 2021-01-19 16:52:05 +05:30
Sojan 0f313875f7 Bump version to 1.12.1 2021-01-19 16:51:11 +05:30
Sojan JoseandGitHub f36af7a7de chore: Fix db:prepare error in deployments (#1668)
Fixes #1667
2021-01-19 16:47:25 +05:30
Pranav Raj SandGitHub 114f00b88a fix: Avoid list-style none in message-content (#1665) 2021-01-19 01:05:15 +05:30
Sojan 1aaced3027 Merge branch 'release/1.12.0' into master 2021-01-18 14:17:44 +05:30
Sojan f50cecf865 Bump version to 1.12.0 2021-01-18 14:13:57 +05:30
Sojan JoseGitHubPranavAlguienSamaScarlett Bidun (scarlettbidun)Sin V (jiiniasu)Diego Vieira (diego-vieira)vfasoulasYovan Lutfi Arya (Regerta)arturczyzewski
b4ef6f64be chore: Update translations (#1661)
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: AlguienSama
Co-authored-by: Scarlett Bidun (scarlettbidun)
Co-authored-by: Sin V (jiiniasu)
Co-authored-by: Diego Vieira (diego-vieira)
Co-authored-by: vfasoulas
Co-authored-by: Yovan Lutfi Arya (Regerta)
Co-authored-by: arturczyzewski
2021-01-18 12:36:26 +05:30
13073629bb feat: Enable Markdown Parsing in emails (#1663)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-18 11:43:31 +05:30
54f15b73d3 feat: Markdown editor support (#1657)
Co-authored-by: Pranav <pranav@chatwoot.com>
2021-01-18 11:20:19 +05:30
58fad2561d chore: Standardize button element (#1633)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-18 00:54:20 +05:30
Pranav Raj SandGitHub cd7f17f280 chore: Update homebrew installation command (#1662) 2021-01-18 00:09:43 +05:30
Pranav Raj SandGitHub ba06fe1cb2 feat: Update notification in account settings (#1660) 2021-01-17 23:59:09 +05:30
a0c33254e7 feat: Team APIs (#1654)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-17 23:56:56 +05:30
dd90e24d02 chore: Add unread notification count API (#1646)
Co-authored-by: Sojan <sojan@pepalo.com>
2021-01-17 22:45:31 +05:30
b6e8173b24 feat: HMAC verification for web widget (#1643)
* feat: HMAC verification for web widget. Let you verify the authenticated contact via HMAC on the web widget to prevent data tampering.
* Add docs for identity-validation

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-17 22:44:03 +05:30
d758df8807 fix: Add correct thread message_id to the email message (#1659)
Co-authored-by: Sojan <sojan@pepalo.com>
2021-01-17 22:43:32 +05:30
14eefe3824 feat: Add Installation onboarding flow (#1640)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-17 14:07:18 +05:30
a5c3c4301c feat: Add support for markdown in messages (#1642)
Co-authored-by: Pranav <pranav@chatwoot.com>
2021-01-15 14:40:50 +05:30
Sony MathewandGitHub 5adbc84e0c feat: Remove un-necessary lock attribute in config (#1656) 2021-01-15 13:49:56 +05:30
Sony MathewandGitHub 18d3c40fb3 feat: installation config in super admin console (#1641)
* feat: installation config in super admin console

* Added the ability for super admins to view, edit and update
installation config values. Also they can add new isntallation config
values. The impact of editing and adding depends on which all
installation config values are being used in the code.
* Known limitation now: Ability to edit hash values (for eg: feature
flags) are disabled. This requires more work and will be taken up in
a secondary set of changes.
* Minor UX improvement. Clicking on the Sidekiq option in the super
admin siebar will now open the sidekiq dashboard in a new tab rather
than in the same tab that you were using super admin.

* fix: method name fix in custom adminsitrate field

* feat: added locked attribute to global config
* Added the locked attribute to instalaltion config table. Added
necessary migrations. Added changes in config loader.
* Added the changes on the installation config yml
* Locked the account feature defaults in code

* feat: show only editable configs in admin console
* Added a new scope in installation config model
* Added scope in adminstrate controller for installation_config

* fix: new installation config create error
* Fixed the error in new installation config create

* fix: specs coverage
* Added specs for installation config super admin controller

* chore: update git ignore with encrypted config ext
2021-01-15 13:21:53 +05:30
Sojan JoseandGitHub 2e19de5d01 chore: Update Contact Inbox create API documentation (#1650) 2021-01-14 20:36:04 +05:30
Sojan JoseandGitHub 7542330d61 feat: Add Platform APIs (#1456) 2021-01-14 20:35:22 +05:30
Pranav Raj SandGitHub 75c2a7cb2f fix: Resolve name only if assignee exists during unassignment (#1649) 2021-01-14 14:21:41 +05:30
Suhavi SandhuandGitHub dad737021f Adds character count to reply box 😳 (#1634)
* Added characters remaining to reply box

* Changed warning text for character length

* Decreased font size of message
2021-01-13 19:16:45 +05:30
fd181f18a1 feat: Update reply box UI 👀 (#1623)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-13 18:06:25 +05:30
Muhsin KelothandGitHub 2d5aa9d3bd chore: Add count and current page in notification meta details (#1619) 2021-01-13 17:04:27 +05:30
Pranav Raj SandGitHub 8c66dbd342 fix: Labels cannot be added to conversations (#1644) 2021-01-13 12:15:11 +05:30
764c90174e feat: Improve sidebar UI, add emoji icons instead of ionicons (#1605)
Co-authored-by: Pranav <pranav@chatwoot.com>
2021-01-12 14:45:10 +05:30
Sojan JoseandGitHub 346830ab1d feat: Add Cron Jobs In Chatwoot and update installation notice (#1630) 2021-01-11 17:34:41 +05:30
Pranav Raj SandGitHub 160a6fc6cf feat: Save UI state in the database (#1635)
feat: Save UI state in the database
2021-01-10 19:25:33 +05:30
37d8e1c9a0 chore: Update translations, enable Swedish (#1628)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sin V (jiiniasu)
2021-01-09 13:29:02 +05:30
Pranav Raj SandGitHub a9344fbf4c fix: Add missing switch_locale on DashboardController (#1631) 2021-01-09 01:43:17 +05:30
Pranav Raj SandGitHub df27aab959 fix: Include missing file for labels (#1629) 2021-01-08 21:01:45 +05:30
Sojan JoseandGitHub 7884090551 chore: Enable updating conversation additional attributes (#1611)
- Enable updating additional attributes via conversation API
- Handle the case when additional_attributes is nil

Fixes: #1357
2021-01-07 13:47:38 +05:30
Nithin David ThomasandGitHub 64b0d48dbf Add shadow utility variables (#1620) 2021-01-06 22:54:36 +05:30
Pranav Raj SandGitHub 03487019b6 chore: Add steps to enable inbound_emails in the account (#1614) 2021-01-06 18:16:38 +05:30
3d2db95417 feat: Add preview for attachment messages (#1562)
Add preview for pending messages and attachments

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-01-06 17:56:29 +05:30
Sojan JoseandGitHub db189e3c26 chore: Sync the schema and migrations (#1610) 2021-01-06 11:36:45 +05:30
627d3a575a chore: Automate conversation display_id generation with db triggers (#1412)
Automate conversation display_id generation with db triggers

Co-authored-by: Saurabh Mehta <saurabh1.mehta@airtel.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2021-01-05 20:07:04 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
45059b6fe9 chore: Bump axios from 0.19.2 to 0.21.1 (#1603)
Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v0.21.1/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-05 13:10:03 +05:30
Pranav Raj SandGitHub b49ce6b624 security: Update azure-storage-blob to fix nokogiri security issue (#1602) 2021-01-05 12:55:28 +05:30
Pranav Raj SandGitHub 1266f0ab8c feat: Add link to the Twitter profile of the sender (#1597) 2021-01-05 10:06:40 +05:30
Pranav Raj SandGitHub a2d6fa0f74 feat: API to add label to contacts (#1563) 2021-01-03 20:07:57 +05:30
Pranav Raj SandGitHub ea08fbcac4 chore: Update license year and company name (#1575) 2021-01-03 19:56:06 +05:30
8b7e43bdbb fix: Remove Twitter links rendered in messages (#1570)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2020-12-31 19:17:00 +05:30
Pranav Raj SandGitHub d35ce1b868 fix: Update listen gem (#1569) 2020-12-31 19:00:03 +05:30
Sojan JoseGitHubPranav Raj SYovan Lutfi Arya (Regerta)Goudarz Jafari (Goudarz)korhovfasoulas
7672e49148 chore: Update translations (#1561)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Yovan Lutfi Arya (Regerta)
Co-authored-by: Goudarz Jafari (Goudarz)
Co-authored-by: korho
Co-authored-by: vfasoulas
2020-12-29 13:18:22 +05:30
Pranav Raj SandGitHub 811657c9e7 feat: API to allow agents to delete a message (#1353) 2020-12-28 23:36:50 +05:30
Pranav Raj SandGitHub 08f1e0eb32 chore: Add docs about GCS Storage (#1560) 2020-12-28 23:15:45 +05:30
Pranav Raj SandGitHub 99125d3b9c chore: Add limitations section to Heroku (#1559) 2020-12-28 21:24:38 +05:30
4a9e665f94 chore: Use font subsetting for Inter (#1553)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2020-12-27 20:24:04 +05:30
Pranav Raj SandGitHub bde323ffaf chore: Remove Ionicons TTF references (#1554) 2020-12-27 20:12:08 +05:30
Nithin David ThomasandGitHub 56280eaf35 chore: Remove beta tag from sidebar name (#1552) 2020-12-26 11:18:56 +05:30
Nithin David ThomasandGitHub 7c62d3629c feat: Add pending message on dashboard (#1547) 2020-12-25 13:15:01 +05:30
3e61ea5cfa feat: Change the date format display in widget (#1528)
Co-authored-by: Pranav <pranav@chatwoot.com>
2020-12-24 18:53:47 +05:30
+5
Sojan JoseGitHubPranavAlguienSamaYovan Lutfi Arya (Regerta)FrederikAmbler (ambler)Hossein Sadeghi (ssageghi)korhovfasoulasThiago Ramos (thiago)Ehab hakawati (ehab.hakawati)Karl Marx (taylanguney)Fernando Sousa (Fernando)Matt (duartemvix)
677f56f802 chore: Update translations (#1536)
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: AlguienSama
Co-authored-by: Yovan Lutfi Arya (Regerta)
Co-authored-by: Frederik
Co-authored-by: Ambler (ambler)
Co-authored-by: Hossein Sadeghi (ssageghi)
Co-authored-by: korho
Co-authored-by: vfasoulas
Co-authored-by: Thiago Ramos (thiago)
Co-authored-by: Ehab hakawati (ehab.hakawati)
Co-authored-by: Karl Marx (taylanguney)
Co-authored-by: Fernando Sousa (Fernando)
Co-authored-by: Matt (duartemvix)
2020-12-22 18:01:10 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fe6571c3ff chore: Bump node-notifier from 8.0.0 to 8.0.1 (#1538)
Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/v8.0.1/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-22 16:17:01 +05:30
Pranav Raj SandGitHub 9d3dda9a61 feat: Add full name to the user signup form (#1534) 2020-12-21 14:05:19 +05:30
Muhsin KelothandGitHub 796e376fa7 feat: Add smart app banner in website for iOS (#1531) 2020-12-20 11:52:40 +05:30
Muhsin KelothandGitHub f3f2542bae fix: Update agent select placeholder translation (#1533) 2020-12-20 11:51:20 +05:30
Pranav Raj SandGitHub 8e2b4acc43 chore: Remove account.destroy listener (#1530) 2020-12-19 18:11:43 +05:30
Muhsin KelothandGitHub 090b716ec1 chore: Fix translation link in readme (#1525) 2020-12-18 12:42:14 +05:30
Nithin David ThomasandGitHub dd3d91c67e feat: Add link for "intitated from" in sidebar (#1523) 2020-12-18 01:19:44 +05:30
Sojan fa883a2780 Merge branch 'release/1.11.1' into master 2020-12-16 15:34:10 +05:30
Sojan a214372c7c Bump version to 1.11.1 2020-12-16 15:32:44 +05:30
Pranav Raj SandGitHub 50f87f373e fix: Use empty object if additional_attribute is null (#1520) 2020-12-16 15:11:53 +05:30
Sojan 6373e6dec8 Merge branch 'release/1.11.0' into master 2020-12-16 00:40:19 +05:30
Sojan 49a12bd560 Bump version to 1.11.0 2020-12-16 00:39:02 +05:30
Sojan JoseandGitHub 610142c1b8 chore: Enable Korean (ko) (#1514) 2020-12-16 00:35:40 +05:30
Pranav Raj SandGitHub ac7fdaa997 chore: Add documentation for Maxmind geocoder setup (#1518) 2020-12-16 00:32:05 +05:30
Pranav Raj SandGitHub 0619894560 feat: Download Agent wise report (#1517) 2020-12-15 23:35:03 +05:30
Pranav Raj SandGitHub e6f7f5530b chore: Fix i18n_key for apps (#1516) 2020-12-15 16:32:13 +05:30
Pranav Raj SandGitHub faafdc3bf8 chore: Add missing label to locale file (#1513) 2020-12-15 01:24:56 +05:30
Pranav Raj SandGitHub f0fd93bfea chore: Update Mac OS setup guide (#1512) 2020-12-15 01:17:17 +05:30
Pranav Raj SandGitHub edb09d5a9c chore: Improve location display in sidebar (#1509)
- Log IP Address on widget load
- Save country code to contact
2020-12-13 22:23:56 +05:30
Pranav Raj SandGitHub 060ef4a427 chore: Add steps for copying targets in linux VM (#1508) 2020-12-12 13:25:28 +05:30
f9bd447912 chore: Upgrade vue-i18n to 8.x (#1383)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-12-12 12:08:36 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7f2f984bea chore: Bump ini from 1.3.5 to 1.3.7 (#1507)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-12 00:01:14 +05:30
Pranav Raj SandGitHub 1ade4f75ea chore: Ingore case while searching contact name, email (#1505) 2020-12-11 23:25:00 +05:30
Pranav Raj SandGitHub b6ca77158c fix: Limit the number of unread messages returned in the API (#1504) 2020-12-10 23:30:38 +05:30
Pranav Raj SandGitHub 88c4b63eec chore: Add slack external_source_id for outgoing messages (#1503) 2020-12-10 22:53:49 +05:30
Sojan JoseandGitHub 1f02c09a41 chore: Setup dev env with Github Codespaces [alpha] (#1282)
Easily spin up a Chatwoot development environment with Github Codespaces.
2020-12-09 17:01:28 +05:30
Sojan JoseGitHubPranav Raj SreepuramYovan Lutfi Arya (Regerta)Matt (duartemvix)vfasoulasFernando Sousa (fernando)korho
e07ecd547b chore: Update translations (#1502)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
Co-authored-by: Yovan Lutfi Arya (Regerta)
Co-authored-by: Matt (duartemvix)
Co-authored-by: vfasoulas
Co-authored-by: Fernando Sousa (fernando)
Co-authored-by: korho
2020-12-09 16:43:51 +05:30
Pranav Raj SandGitHub 70002afc60 chore: Move missing text to translation files (#1501) 2020-12-08 23:31:25 +05:30
Pranav Raj SandGitHub 870a24126e fix: Display assignee only if the assignee has access to the account (#1500) 2020-12-08 22:49:47 +05:30
Sojan JoseGitHubPranav Raj SreepuramMichael (msmits2011)pixpackvfasoulaskorhoYovan Lutfi Arya (Regerta)
2880f4942a chore: Enable Finnish, Indonesian languages (#1495)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
Co-authored-by: Michael (msmits2011)
Co-authored-by: pixpack
Co-authored-by: vfasoulas
Co-authored-by: korho
Co-authored-by: Yovan Lutfi Arya (Regerta)
2020-12-08 00:05:07 +05:30
Pranav Raj SandGitHub 594871ed96 chore: Fix translation issues (#1494) 2020-12-07 20:11:27 +05:30
Pranav Raj SandGitHub 94c231366a feat: Allow only image, pdf, audio, video, csv on file uploader (#1492) 2020-12-07 13:48:41 +05:30
Pranav Raj SGitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c87cdf25c5 chore: Upgrade highlight.js to 10.4.1 (#1483)
Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 9.18.5 to 10.4.1.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/master/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/9.18.5...10.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-05 01:22:16 +05:30
Pranav Raj SandGitHub 5e190aad3c fix: Check if the argument is an empty string (#1474) 2020-12-05 00:56:33 +05:30
mike9011andGitHub e1d4584770 chore: Fix widget translation for nl (#1478) 2020-12-04 01:26:24 +05:30
Pranav Raj SandGitHub af2fb1b146 fix: Add worker to the formation (#1470) 2020-12-01 14:56:05 +05:30
Sojan JoseGitHubPranav Raj SreepuramАлексей Чертановскийcanbaran011Jonáš Loskot (Fjuro)wanhai huangMatt (duartemvix)chinyaevKarl Marx (taylanguney)
a5ceddc454 chore: Enable Czech(cs), Turkish(tr), update translations (#1466)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
Co-authored-by: Алексей Чертановский
Co-authored-by: canbaran011
Co-authored-by: Jonáš Loskot (Fjuro)
Co-authored-by: wanhai huang
Co-authored-by: Matt (duartemvix)
Co-authored-by: chinyaev
Co-authored-by: Karl Marx (taylanguney)
2020-12-01 13:15:17 +05:30
Pranav Raj SandGitHub 64733ca3bc fix: Move integration text to translation file (#1463)
- Move integration text to translation file
- Split switch_locale
2020-11-30 16:24:54 +05:30
Nithin David ThomasandGitHub d51c5d5768 chore: Add click interaction for conversation list (#1460) 2020-11-29 13:28:36 +05:30
Pranav Raj Sreepuram bb31b21060 Merge branch 'master' into develop 2020-11-27 14:43:02 +05:30
Tim CowlishawandGitHub d5a126745e fix: GCS credentials dont need to be parsed as JSON (#1429) 2020-11-27 14:39:25 +05:30
Tristan RoscoeandGitHub 88f5f825b7 fix: Add branch variable to Linux VM setup script (#1462) 2020-11-27 13:37:57 +05:30
Pranav Raj SandGitHub f397c0c087 chore: Send typing events on keyup, not on focus (#1461) 2020-11-27 00:17:55 +05:30
a988724c91 feat: Authenticate by SSO tokens (#1439)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-25 13:59:38 +05:30
Vishal PandeyandGitHub cb2a528be6 fix: Label overflow using text-truncate (#1448) 2020-11-25 12:52:39 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Pranav Raj Sreepuram
34c1091d55 chore: Bump highlight.js from 9.18.1 to 9.18.5 (#1453)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-25 12:50:34 +05:30
Sojan JoseGitHubSamuel Rasmussenwanhai huangMattPetteri PucilowskiАлексей Чертановский@vfasoulasGoudarz Jafari
d88118e8d5 chore: Enable Danish language (#1443)
Co-authored-by: Samuel Rasmussen
Co-authored-by: wanhai huang
Co-authored-by: Matt
Co-authored-by: Petteri Pucilowski
Co-authored-by: Алексей Чертановский
Co-authored-by: @vfasoulas
Co-authored-by: Goudarz Jafari
2020-11-24 23:07:51 +05:30
30802e0c13 feat: Ability to set installation-wide default locale (#1433)
* Dashboard locale can be set via env variable
* Change account locale based on registration page
* Set account locale if available

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-24 18:34:31 +05:30
Adam ZyskoandGitHub dffc888f9c feat: Create superadmin in seeds (#1442)
Create SuperAdmin in seeds scripts except on production
2020-11-24 11:22:18 +05:30
Vishal PandeyandGitHub 942d1fd0af feat: Search contacts using phone number (#1440) 2020-11-23 11:00:07 +05:30
Pranav Raj SandGitHub 4fe29fefb4 fix: Add missing close button if bubble is hidden (#1435) 2020-11-23 10:49:28 +05:30
fcf91f60fb chore: Remove invalid quotes in Dockerfile instructions (#1431)
Co-authored-by: hiaselhans <simon.klemenc@gmail.com>
2020-11-22 21:50:56 +05:30
Pranav Raj SandGitHub be2d3ea124 fix: Update agent list when the user changes their presence (#1436) 2020-11-21 22:43:27 +05:30
Adam ZyskoandGitHub 61d26f71c1 chore: bump ruby from 2.7.1 to 2.7.2 (#1426)
Closes:  #1399
2020-11-20 15:38:13 +05:30
Pranav Raj SandGitHub 29bd05ccfb chore: Add documentation on translation process (#1424) 2020-11-18 15:27:50 +05:30
Pranav Raj Sreepuram c40ba0d3dd Bump version to 1.10.0
Signed-off-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-17 15:35:37 +05:30
Sojan d5dff3c710 Merge branch 'release/1.10.0' into master 2020-11-17 11:45:30 +05:30
Pranav Raj SandGitHub 3ee453c01e fix: Avoid keys getting translated in availability (#1418) 2020-11-17 10:39:46 +05:30
Pranav Raj SandGitHub 2d70131097 fix: Remove duplicate API calls for conversation (#1419) 2020-11-17 09:15:57 +05:30
Sojan JoseandGitHub 9d2542eecd chore: Enable Japanese, update translation from Crowdin (#1417) 2020-11-16 23:11:14 +05:30
481baa32ba chore: Use translated text in the language menu (#1377)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-16 20:39:52 +05:30
மனோஜ்குமார் பழனிச்சாமிandGitHub f4facee8d8 chore: Update text on PR template, inboxMgmt.json (#1410) 2020-11-16 19:50:32 +05:30
Sojan JoseandGitHub eb2ded6f65 feat: Agent & Inbox Report APIs (#1391) 2020-11-16 19:41:52 +05:30
Pranav Raj SandGitHub faaed17418 fix: Fire query only if search term is available (#1413) 2020-11-16 13:08:36 +05:30
Pranav Raj SandGitHub ef99fd3311 feat: Ignore tweets from blocked users (#1408) 2020-11-16 10:46:53 +05:30
Sojan JoseandGitHub 563da0e052 feat: Use gravatar URL for contacts and users if no image available (#1407) 2020-11-13 19:56:30 +05:30
Nithin David ThomasandGitHub f275cf8809 chore: Remove duplicate CSS property (#1404) 2020-11-13 00:18:12 +05:30
Pranav Raj SandGitHub 5c3de5e095 fix: Enhance CRM UI (#1397)
* feat: Sort by name
* feat: Fetch labels from sidebar
* Remove unused language file
* Add beta tag to contacts
* Add timeMixin, reduce font-size
* Remove unused methods
* Remove unused prop
* Disabled footer if no contacts or invalid page
* Add keyup for input
* Fix conversation not loading if there are no active conversations
* return last_seen_at as unix time
* Fix contact edit modal
* Add loader for edit contact button
* Fix review comments
2020-11-11 16:02:14 +05:30
David SteinbauerandGitHub 32fce96503 chore: Update DE translation (#1393) 2020-11-11 10:51:25 +05:30
f214c9c47c feat: Add Contacts page (#1335)
Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-11-10 15:25:26 +05:30
Pranav Raj SandGitHub 2babfd6148 fix: Add a check for thread_ts (#1389)
- If no thread timestamp is available, ignore the message
- Add specs to cover the case
2020-11-09 22:01:57 +05:30
7718cf7d2c feat: Add global message search (#1385)
* feat: Search messages by content

* Fix search UI

* Add specs

* chore: Filter search results

* Update highlight logic

* Rename query to searchTerm

Co-authored-by: Sojan <sojan@pepalo.com>
2020-11-08 01:46:45 +05:30
Sivin VargheseandGitHub 22683cae66 feat: Sort labels on sidebar by alphabetical order (#1387) 2020-11-07 12:21:34 +05:30
Sony MathewandGitHub 39c2270227 fix: pg pass printed by docker container (#1382)
* fix: pg pass printed by docker container (#1371)

The "POSTGRES_PASSWORD" variable setting inside the entrypoint script
of the rails docker container was printed in the logs when the
container was run using docker compose.

Fixed this by removing this password being set in this script.
Added env file from root directory to the container
Updated the tailwind evrsion in yarn lock

* fix: moved pg database url check in the entrypoint to another helper

created a new helper docker/entrypoints/helpers/pg_database_url.sh
to parse the databse url and export the postgres host, user and
port.

With this the pg is_ready check falls to a common format rather
than two formats depending on DATABASE_URL env variable is
present or not.

* fix: rename pg ready variable in rails entrypoint
2020-11-06 00:06:07 +05:30
Muhsin KelothandGitHub afa234a207 feat: Add status color for items in availability status menu (#1380) 2020-11-04 12:23:44 +05:30
Akash SrivastavaandGitHub 074084b258 feat: Auto resolve conversations after n days of inactivity (#1308)
fixes: #418
2020-11-01 12:53:25 +05:30
Adam ZyskoandGitHub 65ed4c78a4 feat: Business hours
Data models and APIs for business hours

ref: #234
2020-11-01 00:14:33 +05:30
Pranav Raj SandGitHub 3d64ba49fc chore: Upgrade tailwindcss to 1.9.x (#1376) 2020-10-31 15:32:55 +05:30
Yih YangandGitHub 12b7358773 feat: Add messages on mute / unmute actions (#1373) 2020-10-30 22:27:25 +05:30
Nico385412andGitHub 84ce0a9054 fix: Make the bubble text not selectable (#1294) 2020-10-30 12:06:51 +05:30
RicardoandGitHub 85738f6408 Added missing keywords (#1365) 2020-10-28 02:14:58 +05:30
Sojan JoseandGitHub 1d9debaee0 feat: IP lookup (#1315)
- feature to store contact IP for accounts
- IP lookup through geocoder gem
- ability to do IP lookup through external APIs
- add commit hook to prevent push to develop and master
- migrations to fix default values for jsonb columns
2020-10-28 02:14:36 +05:30
AbhishekandGitHub ff96d43953 feat: notify on slack disconnect (#1323) 2020-10-28 00:22:57 +05:30
Hiroshi SHIBATAandGitHub 9045b8d9ca chore: Fixed typos (#1369) 2020-10-27 20:22:55 +05:30
Pranav Raj SandGitHub d0f2ed38c1 fix: Add lib/azure to autoload ignore list (#1368) 2020-10-27 18:48:23 +05:30
Sojan JoseandGitHub 46098f2970 chore: Monkey patch Azure Storage Service (#1366)
Monkey patch azure storage service until the changes come into rails stable versions
2020-10-26 00:31:19 +05:30
Pranav Raj SandGitHub fa864cc9ee fix: Add a full width image view to fix resolution issues (#1363) 2020-10-26 00:28:23 +05:30
Pranav Raj SandGitHub 54214c73aa fix: Update production installation setup script for Ubuntu 20.04 (#1364)
Setup script for Ubuntu 20.04

Fixes: #1364
2020-10-25 22:40:13 +05:30
Adam ZyskoandGitHub f38f778091 chore: Add translation text for PL in the widget (#1360) 2020-10-23 12:33:39 +05:30
Pranav Raj SandGitHub b9be43b276 fix: Add compact type, fix spacing in contact panel (#1352)
* fix: Add compact type, fix spacing in contact panel

* Set padding-top, padding-bottom
2020-10-21 15:18:36 +05:30
Pranav Raj SandGitHub 552df63621 fix: Show File Upload for API Inbox (#1356) 2020-10-21 13:03:04 +05:30
Ronald WalkerandGitHub cbe9e06472 chore: DRY up check_authorization method (#1351) 2020-10-20 19:22:21 +05:30
Sojan JoseandGitHub bbef03edea chore: Update documentation for inbound email service (#1354) 2020-10-20 18:35:40 +05:30
Sojan cf7271ecfb Merge branch 'release/1.9.0' into master 2020-10-20 12:32:57 +05:30
Sojan c7402c6c3f chore: Bump up version to 1.9.0 2020-10-20 12:31:16 +05:30
Muhsin KelothandGitHub 9e3b0f0731 fix: name and email address overflow issue in customer side panel (#1348)
* Complete name and email address overflow  issue

* Changes as per review

* Code cleanup
2020-10-19 14:57:16 +05:30
Pranav Raj SandGitHub 85514cae8d feat: Display reply time in widget (#1349)
Fixes #1132
2020-10-18 23:32:22 +05:30
RicardoandGitHub bd11b2ec58 chore: Update Spanish translation (#1342) 2020-10-17 16:02:08 +05:30
Jon EvansandGitHub 62b4ce2be1 fix: Improve mobile styles for registration view (#1344) 2020-10-16 22:05:07 +05:30
Pranav Raj SandGitHub 666948b809 chore: Reduce the click area on Branding (#1340) 2020-10-15 00:11:47 +05:30
Pranav Raj SandGitHub 0bea0217b4 chore: Use full name in activity message, fix specs (#1339) 2020-10-14 00:16:35 +05:30
Pranav Raj Sreepuram 4a2a309d18 Use name instead of display_name in the dashboard 2020-10-13 13:03:55 +05:30
Pranav Raj SandGitHub 2c324d9421 feat: Allow custom email address for inbox (#1336) 2020-10-11 23:24:11 +05:30
Pranav Raj SandGitHub 58c0792920 fix: Remove duplicate message in slow networks (#1332) 2020-10-11 20:24:26 +05:30
Sojan JoseandGitHub 59bee66e63 chore: Handle exceptions on external URL calls (#1334) 2020-10-11 20:22:21 +05:30
7d409321e9 fix: Truncate long label names in the sidebar (#1309)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-10-10 22:40:11 +05:30
Pranav Raj SandGitHub 3bb2d27646 chore: Use agent partial instead of user in conversation API (#1333) 2020-10-10 21:57:09 +05:30
Sojan JoseandGitHub f11d7fe992 chore: Block Search bots from rendering widget (#1331)
Search bots trying to render the widget ends up throwing errors.
2020-10-10 11:48:31 +05:30
5d5d2f9779 chore: Update contribution guidelines (#1326)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-10-09 14:08:43 +05:30
Sony MathewandGitHub e01fdb5f00 chore: refactored redis config (sentinel related) (#1327)
Refactored the redis config module which had redis sentinel related
configs. Also changed the specs accordingly.
2020-10-09 12:37:42 +05:30
Sony MathewandGitHub b1a8430258 fix: Security: CVE-2020-8264 (#1328) (#1329)
* fix: Security: CVE-2020-8264 (#1328)

* fix: Upgraded rails version to 6.0.3.4 for Security: CVE-2020-8264
* Fixed a rubocop linter issue with string inetrpolation also.
2020-10-09 11:33:51 +05:30
Dmitriy ShcherbakanandGitHub ecebe163e1 feat: Ability to unmute muted conversations (#1319) 2020-10-08 12:02:08 +05:30
Vishal PandeyandGitHub 2aad33a5be Bugfix: Integrations page is broken on safari (#1320)
Fixes #1196
2020-10-07 22:02:08 +05:30
Pranav Raj SandGitHub db1953de24 fix: Add default 404 param on gravatar (#1316) 2020-10-05 23:31:23 +05:30
Sojan JoseandGitHub 88b2469dc8 feat: Add API to get the active contacts (#1313) 2020-10-05 23:30:27 +05:30
Pranav Raj SandGitHub 11725de09a chore: Enable Vietnamese in languages (#1314) 2020-10-05 22:53:24 +05:30
399f9e004a fix: Use last_activity_at instead of updated_at for sorting (#1281)
Co-authored-by: Akash Srivastava <akash.srivastava.1911@gmail.com>
2020-10-05 22:52:43 +05:30
ı ɑɷ ɖεɾεƙandGitHub ee119b2174 chore: Update translation for vietnamese (#1312) 2020-10-05 19:55:18 +05:30
Sojan JoseandGitHub e44afa03f3 chore: Prevent i18n config bleeding across requests (#1214) 2020-10-05 17:55:46 +05:30
AbhishekandGitHub 77d380dd6b chore: refactor redis config (#1310)
- refactor Redis config in Redis::Config Module
-  unit tests for Redis::Config module
2020-10-05 17:31:10 +05:30
Narendran KannanandGitHub 1e1300c9d2 fix: Add word break for files with long name (#1306) 2020-10-05 13:23:38 +05:30
SarawutKlandGitHub df527088e9 fix: Replace Whatsapp inbox icon (#1311) 2020-10-04 22:57:11 +05:30
ArmanandGitHub 3d379b071d feat: use gravatar if no avatar image (#1307)
Fixes:  #1240
2020-10-04 16:25:22 +05:30
AbhishekandGitHub 807f79ef5d feat: support for Redis sentinel (#1301)
closes: #925
2020-10-03 15:24:33 +05:30
Zero KingandGitHub db4997c07f fix: Array length check (#1300) 2020-10-03 14:07:50 +05:30
AbhishekandGitHub 70f08103aa feat: Activity message for label addition & deletion (#1291)
Fixes: #1022
2020-10-02 16:33:59 +05:30
Dmitriy ShcherbakanandGitHub 98cb09104e chore: Refactor DeviseOverrides::ConfirmationsController#create (#1297) 2020-10-02 15:27:26 +05:30
b81eef6ffd chore: Add translation for Vietnamese (#1292)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-10-02 11:28:15 +05:30
127ffda762 feat: Change availability status from sidebar (#1288)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-10-02 11:16:12 +05:30
Jonathan ComoandGitHub f61b731fb3 fix: Call hasUserKeys() on user argument (#1295) 2020-10-02 10:17:12 +05:30
AbhishekandGitHub 5cd08b3f98 chore: self-assign conversation activity message (#1293) 2020-10-02 00:41:23 +05:30
Sojan JoseandGitHub b862817b29 feat: Enable reauthorization for Facebook (#1286) 2020-09-30 01:12:32 +05:30
Pranav Raj SandGitHub 99ca54fd3c fix: Remove keys for reports from translation file (#1279) 2020-09-27 18:56:52 +05:30
Pranav Raj SandGitHub dbd1720aeb chore: Add a check for data diff in setUser call (#1272) 2020-09-26 22:33:20 +05:30
701eccb35c Feature: Knowledge Base APIs (#1002)
- Introduce models & migrations for portals, categories, folders and articles
- CRUD API for portals
- CRUD API for categories

Addresses: #714

Co-authored-by: Sojan <sojan@pepalo.com>
2020-09-26 02:32:34 +05:30
David SteinbauerandGitHub 4b27ac63d4 chore: Add widget text translations for German (#1276) 2020-09-25 21:36:31 +05:30
Pranav Raj SandGitHub d6ada922c8 chore: Fix wrong documentation to set a label (#1269) 2020-09-24 23:20:25 +05:30
Sojan JoseandGitHub 532331edb6 feat: Ability to search conversation with message content (#1265)
- API end point which takes message content as search parameter
- end point supports additional filtering with labels and inbox ids
- swagger doc
2020-09-23 15:27:41 +05:30
Pranav Raj SandGitHub bc8becf49c chore: Update website-sdk documentation (#1267)
Update the `website-sdk` documentation to reflect the feedback on setUser method from a customer
2020-09-23 15:27:11 +05:30
17e5c01948 chore: Update zh_TW i18n files (#1262)
Co-authored-by: JackTsai <jacktsai@larvata.tw>
2020-09-22 19:16:00 +05:30
Sony MathewandGitHub 381c448627 fix: Email encoding issue - utf8 (#1264)
There were issues in parsing Arabic or UTF characters (emojis)
correctly for the incoming emails.

All these characters were converted to question marks which is
teh fallback character when an encoding is enforced and there is
a missing matching character.
2020-09-22 11:26:41 +05:30
Sony MathewandGitHub f9b0427751 feat: email channel backend (#140) (#1255)
* feat: added support mailbox to handle email channel (#140)

Added a new mailbox called 'SupportMailbox' to handle all the
incoming emails other than reply emails.

An email channel will have a support email and forward email
associated with it. So we filter for the right email inbox based on
the support email of that inbox and route this to this mailbox.

This mailbox finds the account, inbox, contact (create a new one
if it does not exist) and creates a conversation and adds the
email content as the first message in the conversation.

Other minor things handled in this commit:

* renamed the procs for routing emails in application mailbox
* renamed ConversationMailbox to ReplyMailbox
* Added a fallback content in MailPresenter
* Added a record saving (bang) versions of enabling and disabling
features in Featurable module
* added new factory for the email channel

refs: #140
2020-09-21 22:44:22 +05:30
Vishal PandeyandGitHub 313b2da703 bugfix: fix file uploads not showing original file name
fixes: #1246
2020-09-21 18:42:30 +05:30
Pranav Raj SandGitHub ea6577af6d fix: Remove agent keys from translation file (#1261) 2020-09-20 22:19:34 +05:30
Pranav Raj SandGitHub 0deb1af852 chore: Add a check for defined labels in SDK API (#1259) 2020-09-20 19:29:39 +05:30
Pranav Raj SandGitHub cdd428f503 chore: Add browser logs and server logs to the template (#1260) 2020-09-20 19:10:08 +05:30
Sony MathewandGitHub fc7b84d612 Chore: Fix N+1 queries in dashboard side (#1254)
* Chore: Fix N+1 queries in dashboard side

Fixed a couple of N+1 queries fired on the dashboard side of
the app to improve performance.
2020-09-19 12:46:34 +05:30
Sojan JoseandGitHub 74d07c876e chore: Fix RestClient::GatewayTimeout, label_list of NilClass (#1243) 2020-09-18 18:50:53 +05:30
Pranav Raj SandGitHub 646746aa10 fix: Check medium to decide 24 hour window (#1245) 2020-09-17 23:32:19 +05:30
Pranav Raj SandGitHub 8b953917e1 chore: Upgrade selfsigned to fix CVE-2020-7720 (#1242) 2020-09-17 13:23:23 +05:30
Pranav Raj SandGitHub 5ae3026125 fix: Add available_name method to agent_bot (#1238) 2020-09-16 11:46:07 +05:30
Sojan c9a56f1f02 Merge branch 'release/1.8.0' into master 2020-09-14 18:10:02 +05:30
Sojan 49b4c2ae07 chore: Bump up version 2020-09-14 18:08:53 +05:30
Pranav Raj SandGitHub 1312d07aa2 chore: Remove momentjs, use date-fns (#1233) 2020-09-14 15:14:26 +05:30
Pranav Raj SandGitHub f3a357d832 chore: Remove emojione, cleanup styles (#1232)
* chore: Remove `emojione`, cleanup styles

* Move size to variables

* Remove unused categories
2020-09-13 22:49:01 +05:30
Sojan 739c062676 chore: Enable an echo id for message create end points 2020-09-13 16:16:52 +05:30
Sojan JoseandGitHub afc062537c chore: Fix integration hooks destroy method (#1224) 2020-09-12 23:09:55 +05:30
fe3cb76a19 chore: allow DATABASE_URL env to take presedence over individual connection params. (#1147)
fixes: #1147 
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-11 14:32:24 +05:30
31c07771e8 feat: Notification on new messages in conversation (#1204)
fixes: #895
fixes: #1118
fixes: #1075

Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-10 19:19:15 +05:30
Pranav Raj SandGitHub 3b92c744d6 fix: Update documentation to use launcherTitle (#1212) 2020-09-09 11:27:31 +05:30
Sojan JoseandGitHub ac5d755545 chore: Update dependencies (#1173) 2020-09-08 11:24:08 +05:30
3ffb29bf4e Chore: Squash previous migrations (#1107)
Fixes: #784
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-07 15:19:41 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3544514470 Chore: Bump http-proxy from 1.18.0 to 1.18.1 (#1203)
Bumps [http-proxy](https://github.com/http-party/node-http-proxy) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/http-party/node-http-proxy/releases)
- [Changelog](https://github.com/http-party/node-http-proxy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/http-party/node-http-proxy/compare/1.18.0...1.18.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-09-06 23:36:57 +05:30
Pranav Raj SandGitHub c668cccb53 chore: Upgrade yargs-parser to fix GHSA-p9pc-299p-vxgp (#1202) 2020-09-06 23:20:18 +05:30
d18c8fc08a chore: Add message_echo listener for Facebook (#1192)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2020-09-04 19:13:47 +05:30
Pranav Raj SandGitHub 715bd368f4 chore: Add alt for bubble icon (#1200) 2020-09-04 19:13:22 +05:30
afb5694ed6 chore: Enable runtime metrics on Heroku (#1178)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-03 15:24:08 +05:30
Pranav Raj SandGitHub e4336ffcb3 chore: Remove unused packages from package.json (#1190) 2020-09-03 14:55:05 +05:30
Pranav Raj SandGitHub 3ac32a3fbd chore: Add documentation to setup Cloudfront as the CDN (#1193)
Add documentation to setup Cloudfront as the CDN
2020-09-03 14:54:11 +05:30
9b23a11c5b chore: Improves styling for conversation header (#1167)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-03 14:11:07 +05:30
Pranav Raj SandGitHub dfb533db8d chore: Improve widget loading performance (#1191)
* Frontend assets url

* Remove font files from widget

* Rename variable to ASSET_CDN_HOST
2020-09-03 13:17:45 +05:30
17968e6d3f bugfix: validate_queue method - map then sort, instead of sort then map (#1187)
Co-authored-by: Sahil Mittal <sahil.mittal@snapdeal.com>
2020-09-02 20:51:40 +05:30
Sony MathewandGitHub cb6fc9fb2e fix: fonts cors issue with cdn (#1182) 2020-09-01 11:39:18 +05:30
Pranav Raj SandGitHub 29d13fbb4f chore: Add documentation for API channel (#1179) 2020-08-30 21:46:36 +05:30
Sojan JoseandGitHub 5ac093fca2 chore: Fix nil class error at bot endpoint (#1177) 2020-08-30 12:36:21 +05:30
Sojan JoseandGitHub 85ae6d92b9 feat: Enable Slack Integration in all channels (#1175) 2020-08-29 01:39:41 +05:30
Pranav Raj SandGitHub 45cd949c40 feat: Add a popout option on webwidget (#1174)
* feat: Add a popout option on webwidget
2020-08-28 17:39:46 +05:30
Sojan JoseandGitHub ce13efd273 chore: Update translations for ar, zh (#1172) 2020-08-26 21:33:52 +05:30
Sojan JoseandGitHub 2193de9853 chore: General fixes and clean up (#1169) 2020-08-25 23:04:02 +05:30
Pranav Raj SandGitHub 124e43b477 chore: Update issue template (#1168) 2020-08-23 21:12:50 +05:30
fe1259a29f feat: Update styles, Add support for Arabic text in emails (#1088)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-08-23 19:58:19 +05:30
Pranav Raj Sreepuram d605619eba Merge branch 'master' into develop 2020-08-23 18:30:14 +05:30
Pranav Raj Sreepuram e1b7165bec chore: Bump version to 1.7.2 2020-08-23 18:29:40 +05:30
Pranav Raj Sreepuram 31fd673f71 Merge branch 'hotfix/1.7.2' into develop 2020-08-23 18:11:27 +05:30
Pranav Raj Sreepuram b38952d6ca Merge branch 'hotfix/1.7.2' 2020-08-23 18:11:13 +05:30
Pranav Raj Sreepuram 37335c413a Fix window.chatwootSettings is undefined 2020-08-23 18:10:36 +05:30
Sojan 62e70ddcc8 chore: Bump versions 2020-08-23 13:55:54 +05:30
Sojan aea5ea3a06 Merge branch 'release/1.7.1' 2020-08-23 13:49:08 +05:30
8cf05f1d9f feat: Ability to edit a contact (#1092)
Ability to edit contact information in conversation sidebar

Co-authored-by: Sojan <sojan@pepalo.com>
2020-08-23 00:05:07 +05:30
Pranav Raj SandGitHub ec6cd4bbba feat: Use order_by_name as default sort order for inbox/user (#1160) 2020-08-22 22:20:22 +05:30
Pranav Raj SandGitHub 5917cd5d98 security: Upgrade webpacker to fix CVE-2020-7660 (#1161)
- security: Upgrade webpack to fix CVE-2020-7660
2020-08-22 22:18:50 +05:30
83eb92e7ff chore: Enable Russian, update translations (#1159)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-22 17:54:16 +05:30
cdd385b269 feat: Custom Attributes for contacts (#1158)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-21 19:30:27 +05:30
Sojan JoseandGitHub 507b40a51d chore: Control rendering contact inbox (#1157) 2020-08-19 23:25:55 +05:30
Pranav Raj SandGitHub e8912655a5 feat: Allow user to change the bubble title using SDK (#1155)
- Allow user to change the bubble title using SDK
- Add docs for enabling expanded bubble
2020-08-19 22:24:02 +05:30
Pranav Raj SandGitHub 662bb882f7 chore: Update API docs (#1153) 2020-08-18 12:14:37 +05:30
Francois Falala-SechetandGitHub dfe4b70d91 chore: update swagger definitions (#1151)
update swagger definitions
2020-08-17 13:07:12 +05:30
22880df429 Feature: Send chat transcript via email (#1152)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-17 11:25:13 +05:30
Pranav Raj SandGitHub 4b70e4e3d6 chore: Update Readme with feature details (#1149) 2020-08-15 13:13:49 +05:30
Pranav Raj SandGitHub 104f1fb1cc Update application_mailer.rb 2020-08-14 23:50:41 +05:30
Pranav Raj SandGitHub f5374e0cd9 chore: Add documentation for DATABASE_URL environment variable (#1146) 2020-08-14 17:29:35 +05:30
be91b322a4 chore: Enable additional attributes in liquid (#1144)
enable additional liquid variables in mailers

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-14 00:47:24 +05:30
Pranav Raj SandGitHub 0117997fb1 chore: Add docs on customizing email template content (#1141) 2020-08-13 15:06:32 +05:30
Sylvain DumontandGitHub 04bce69ded Bugfix: add missing option to s3_compatible to support minio (#1134)
minio doesn't work without force_path_style
more info here: https://kevinjalbert.com/rails-activestorage-configuration-for-minio/
2020-08-11 22:04:06 +05:30
Sojan 2063e248a9 Merge branch 'release/1.7.0' 2020-08-11 10:17:32 +05:30
Sojan JoseandGitHub 4216d63311 feat: Ability to reply to specific tweets (#1117)
Ability to choose a specific tweet to reply to

Fixes #982
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-08-11 09:57:42 +05:30
a6a62d92bf chore: Add Additional Contact APIs (#1130)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-10 12:15:29 +05:30
Pranav Raj SandGitHub ec3c2ed4bb chore: Use 'Lax' instead of 'None' (#1129)
fixes: #919 

Signed-off-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-09 18:13:17 +05:30
Pranav Raj SandGitHub 0adbc346df feat: Add an extended bubble design for the widget (#1123)
* feat: Add a new design for chat bubble

Signed-off-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>

* Add i18n

* Fix stye issues

* Set fixed font-size

* Update docs for bubble
2020-08-09 16:07:32 +05:30
Sojan JoseandGitHub a04ca24def feat: Customisable Email Templates (#1095) 2020-08-06 15:21:06 +05:30
Pranav Raj SandGitHub db877453a4 feat: Disable attachments and emoji picker in the web widget (#1102)
Signed-off-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-08-05 17:46:17 +05:30
Pranav Raj SandGitHub 3b23aa7913 Bugfix: Use server timestamp to set agent_last_seen_at (#1114) 2020-08-03 13:40:20 +05:30
Pranav Raj SandGitHub 941272cccd Bugfix: Move integration logos out of public/assets (#1115) 2020-08-03 13:22:51 +05:30
Pranav Raj SandGitHub a5262a6ff3 chore: Fix scroll in message view (#1113)
* chore: Fix scrolling in messages view

* Remove console.log

* Remove inline-style
2020-08-01 23:36:59 +05:30
Pranav Raj SandGitHub 5e5f34bedc chore: Add an indicator for incoming emails (#1112) 2020-08-01 20:56:47 +05:30
Pranav Raj SandGitHub 6d4cfcceba Chore: Update the usage of available_name instead of name (#1110)
Update the usage of available_name instead of the name
2020-08-01 18:30:47 +05:30
Pranav Raj SandGitHub 1dd3573c39 bug: Fix emails if assignee is nil (#1106) 2020-07-31 15:57:19 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4b773f2a0e Chore: Bump elliptic from 6.5.2 to 6.5.3 (#1104)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-31 00:08:06 +05:30
Pranav Raj SandGitHub a16d2c653d Chore: Update mailer to remove hardcoded twitter link (#1103) 2020-07-30 23:58:42 +05:30
Pranav Raj SandGitHub 2b1d445003 feat: Use display_name instead of name of the agent (#1097)
* feat: Use display_name instead of name of the agent
2020-07-27 22:19:26 +05:30
Pranav Raj Sreepuram f30c8943d9 chore: Display app version on settings/admin area 2020-07-26 21:50:59 +05:30
Pranav Raj SandGitHub 703027b834 chore: Add showBadge prop to tabs-item component (#1096) 2020-07-26 17:46:29 +05:30
89ed0b425b feat: Ability for the logged in user to create a new account (#985)
Co-authored-by: Divyesh <dkothari@box8.in>
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-26 12:54:50 +05:30
Bharat PatodiandGitHub 858b72a404 chore: Update documentation in sdk, channels (#1094)
Fix channels/whatsapp-sms-twilio.md
2020-07-26 12:18:54 +05:30
0f2d3418f9 fix: Add a check for 24 hour window before sending a message (#1084)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2020-07-25 22:54:45 +05:30
Pranav Raj SandGitHub 12ee7e5d82 feat: Add chatwoot:ready event listener on window (#1091)
* feat: Add `chatwoot:ready` event listener on window

* Add specs

* Rename customEventHelper.js -> CustomEventHelper.js
2020-07-25 21:54:58 +05:30
Bharat PatodiandGitHub 80b083c7fc Chore: Fix Docs for FB Twitter Website Channel (#1085) 2020-07-24 23:34:43 +05:30
Karan SharmaandGitHub bb83d6ee4d Chore: modify docker-compose for prod and local setups (#1090) 2020-07-24 23:34:09 +05:30
Pranav Raj SandGitHub c7d962b20f Chore: Remove selectedChat from store (#1087)
* Chore: Remove selected chat from store
2020-07-23 23:33:17 +05:30
e72f29a26e Chore: Update storage to support s3 compatible services (#1082)
This change is to allow using s3 compatible services such as DigitalOcean spaces, Minio, etc

Co-authored-by: petebytes <pete@apsion.com>
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-22 11:53:47 +05:30
d6f309ce22 Chore: Initialize Cypress tests (#1078)
Addresses: #412

Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-21 20:11:22 +05:30
Sony MathewandGitHub fcb7625616 Bug: Fixed quoted text parsing in incoming email (#1076)
* Bugfix: Fixed quoted text parsing in incoming email

We had changed the support email from an account based
only value to account based with fallback on global config
and environment variable.

Incoming email quoted text parsing was still based on
account based support email. Changed this to utilize
the newly introduced fallback values from global config
and environment for parsing quoted text.

* Bugfix: Added one more sender agnostic regex for quoted text parsing
2020-07-21 12:20:46 +05:30
Sojan JoseandGitHub 8079bf50a0 Feature: API Channel (#1052) 2020-07-21 12:15:24 +05:30
Sojan JoseandGitHub fa04098c20 Chore: Run ConfigLoader on migrate (#1072)
We have been duplicating the config loader migration. Hence let's hook it to rake db:migrate.
2020-07-20 19:38:25 +05:30
Sojan JoseandGitHub d800b55ac6 Chore: Add display name to the user (#1067)
* Chore: Adding browser info to web widget triggered event

fixes: #970

* Chore: Rename nickname to display name

references: #972

* Chore: Change nickname in code

* chore: fix errors

* Chore: update nginx config

fixes: #1057

* Chore: Fix specs
2020-07-20 18:28:14 +05:30
Bharat PatodiandGitHub 29838f9424 Fix grammatical issues in Ubuntu Environment Setup (#1070) 2020-07-20 17:43:38 +05:30
Pranav Raj SandGitHub 440f449e24 Enhancement: Remove v-model.trim from reply box (#1071) 2020-07-20 17:39:36 +05:30
Sony MathewandGitHub b803ae3300 Bugfix: Private notes in emails & broken Signup (#1068)
* Bugfix: Private notes in emails

Private notes were sent in the emails as part of
conversation continuity. Fixed this issue.

Also made the changes to not even queue the mails
if message is a private note.

* Bugfix: Change issue with featurable in signup - passing array
* Bugfix: Added specs for checking  private notes being sent in email
2020-07-20 12:47:02 +05:30
Sony MathewandGitHub 96efc44b82 Chore: Feature lock email settings in UI (#1065)
* Chore: Feature lock email settings in UI

The email settings under account settings needed to be
feature locked in a way different from teh current way for it
to be enabled for accounts in a self hosted scenario.

Some refactorings were also done along with this change.

1. There was a feature flag defined in code in account model called
domain_emails_enabled was used to check if the inbound emails was
enabled for the account. But there was already a feature flag called
"inbound_emails" defined in features.yml. So changed to use this to
check if inbound emails are enabled for an account.
2. Renamed and re-purposed existing `domain_emails_enabled` to
`custom_email_domain_enabled` to use for feature toggling the UI
for email settings.
3. To enable & disable multiple features using the featurable concern
we were passing an array of values. Changed this to accept a comma
separated set of values.

* Chore: Feature lock email settings in UI

Fixed the specs for accounts controller & removed
unneccessary code from Account seetings component in UI

* Chore: Convert newlines to <br>s

Removed the layout used while sending replies in
conversation continuity.

Converted the newlines in the messages to <br/> tags
for the correct HTML rendering.

* Chore: Bug fix in reply email domain

Renamed the function custom_email_domain_enabled  to
inbound_email_enabled.

Fixed bug on setting reply emails's domain.
2020-07-19 23:08:07 +05:30
Sojan JoseandGitHub 7607e8edb4 Chore: Enable bot conversations in status dropdown (#1041) 2020-07-19 21:22:12 +05:30
Sony MathewandGitHub 7ca192615d Chore: Move some email configs to ENV variables (#1064)
For the outgoing emails which has dependency on the incoming
part as well like the conversation continuity part, some of the
config variables used were entirely based on the account attributes.

But this is not true in case of self hosted situations where you have
multiple accounts and have a common config for incoming emails.

So moved out some of the attributes entirely dependednt on the account
to ENV with a fallback to the Global config.

Also, with this changes the name of the agent will be shown in the
email clinet with in the conversation rather than just the support
email address. This has a huge UX impact on the cutomer.

Modified all the necessary unit tests to reflect these changes.

Updated the .env.example file for the new ENV variable.
2020-07-19 15:35:55 +05:30
Sony MathewandGitHub 7ef45e5844 Chore: Change the prefix in reply emails (#1060)
* Chore: Change the prefix in reply emails

In conversation continuity the reply to email was looking like

reply+to+{some_random_hex_id}@reply.chatwoot.com

Changed the prefix to just `reply` instead of `reply+to`.

* Chore: Change reply email prefix in outbound emails

Changed the prefix from `reply+to+` to just `reply+` in
the reply emails in the converstaion related outbound emails.
2020-07-19 13:34:34 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
642efe8d40 Chore: Bump lodash from 4.17.15 to 4.17.19 (#1056)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-18 12:05:04 +05:30
Bharat PatodiandGitHub 9e50d22472 Chore: Corrections in docs (#1054) 2020-07-17 20:38:21 +05:30
a18d54b706 Chore: Cleanup attachment handling for Facebook & Whatsapp (#1051)
* Chore: Enable file upload for facebook messenger
* Chore: Fix attachments
* Chore: Fix Specs
* Fix ReplyBox file attachment logic
* Set default value for message

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-07-17 00:32:32 +05:30
Pranav Raj SandGitHub 196741d975 Bug: Fix translated keys for availability statuses in Greek (#1050) 2020-07-15 22:55:57 +05:30
Sony MathewandGitHub d5a6f5e352 Enhancement: ability to send out an email without summary #1048 (#1049)
Right now as part of conversation continuity, we are using the
ConversationReplyMailer which sends a summary of messages including
the incoming messages when an agent replies. Ideally, we want
to send only the reply of that agent and not a summary when
Conversation continuity is enabled. Added the functionality
to send the reply email without summary. Added required unit
tests to cover the changes.

ref: #1048
2020-07-15 16:33:52 +05:30
Bharat PatodiandGitHub a8ce9ae59c Chore: grammatical changes to readme (#1035) 2020-07-14 22:52:48 +05:30
Sojan 196ffe3ea2 Merge branch 'hotfix/1.6.3' into develop 2020-07-14 21:59:52 +05:30
Sojan 80dcc8339e Merge branch 'hotfix/1.6.3' 2020-07-14 21:59:16 +05:30
TianluandSojan ba5539d9bf Chore: dup module name RoundRobin (#1036)
Fix the duplicate module name in migration
2020-07-14 21:56:49 +05:30
TianluandGitHub a260495f3d Chore: dup module name RoundRobin (#1036)
Fix the duplicate module name in migration
2020-07-14 20:16:03 +05:30
Sojan aac3c27483 Merge branch 'hotfix/1.6.2' into develop
# Conflicts:
#	app.json
2020-07-14 11:38:09 +05:30
Sojan a3d14c1884 Merge branch 'hotfix/1.6.2' 2020-07-14 11:37:09 +05:30
Sojan JoseandGitHub 7483796a14 Chore: Update PostgreSQL version to 12 (#1034)
Fixes: #1031
2020-07-14 11:36:31 +05:30
Pranav Raj SandGitHub 5dcc8a9e81 Chore: Add docs on supported features per channel (#1032)
* Chore: Add docs on supported features per channel
2020-07-12 20:35:47 +05:30
Dmitry ShurcoandGitHub 6f47c07362 Update Heroku deploy (#1030) 2020-07-12 17:10:29 +05:30
24101eb117 Feature: Add persian translation (#1017)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-10 21:08:59 +05:30
e8994165ea Chore: Add migration for feature flags (#1024)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-07-10 00:09:40 +05:30
Pranav Raj SandGitHub 929575f11a Chore: Update copy on Signup page (#1023) 2020-07-09 16:28:09 +05:30
Sojan 3593a84f26 Merge branch 'hotfix/1.6.1' into develop 2020-07-08 13:38:54 +05:30
Sojan 6ede64cb6b Merge branch 'hotfix/1.6.1' 2020-07-08 13:38:42 +05:30
Sojan acbb79a7c2 Chore: Fix attribute in reply with summary mailer 2020-07-08 13:37:47 +05:30
Pranav Raj SandGitHub abc335cc8e Feature: Add support for labels in form (#1019) 2020-07-08 13:13:48 +05:30
Sojan d03fad3e1d Merge branch 'release/1.6.0' 2020-07-08 01:00:45 +05:30
a77cc713c2 Chore: Include Tamil, Arabic, other language updates (#1018)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-07-08 00:59:30 +05:30
0fc0dc1683 Chore: Refactor round robin logic (#1015)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-08 00:14:07 +05:30
49db9c5d8a Adds unread message bubbles for widget (#943)
Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-08 00:04:44 +05:30
6a7d810c95 Bug: Set auto width to email input (#1013)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2020-07-06 18:14:19 +05:30
Pranav Raj SandGitHub f8a3f2df27 Chore: Add documentation for Mailgun & Mailchimp (#1014) 2020-07-06 13:28:50 +05:30
Sojan JoseandGitHub e41bd56f41 Chore: Feature Flags for Channels (#1010) 2020-07-06 11:16:19 +05:30
Pranav Raj SandGitHub b633126b35 Chore: Fix spelling mistakes in docs (#1012) 2020-07-06 10:37:51 +05:30
43147b3163 Chore: Fix presence for current user (#1001)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-07-04 20:03:16 +05:30
4612494923 Chore: Fix issues with conversation data models (#1000)
Co-authored-by: Sojan <sojan@pepalo.com>
2020-07-04 19:46:17 +05:30
36661ea45d Enhancement: Add focus state for reply box in dashboard (#999)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-07-04 13:50:44 +05:30
c98907db49 Feature: Availability Statuses (#874)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-04 11:42:47 +05:30
Nithin David ThomasandGitHub bd87927576 Add icon show last reply is from agent on conversation list #997 2020-07-03 23:25:33 +05:30
1b1deb9626 Proposed Enhancements for Chat Bubble Looks in the Dashboard (#992)
* Update Private Note border color

* Added box-shadow to chat bubbles

* Adjustments as suggested in PR #992

Adjustments as suggested in PR #992

* Reintroduced @include border-normal; in L-253

Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-03 23:17:39 +05:30
c0cd747f29 Bug: Fix duplicate messages while using enter key on slow network (#987)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-07-02 11:58:02 +05:30
Steven BucciniandGitHub a699d7bdfe Update documentation with Sendgrid instructions (#994)
Add information about how to integrate with Sendgrid.
2020-07-01 23:02:59 +05:30
83be2e1edb Enhancement: Improve the UX for unread conversations (#986)
Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>
2020-07-01 14:40:21 +05:30
MohmmdandGitHub 534409d25a Enhancement: Use Tahoma as fallback for Arabic characters (#991) 2020-07-01 14:16:08 +05:30
Sojan JoseandGitHub cc02611007 Chore: Convert Message Sender to polymorphic (#740)
Fixes #680
2020-06-27 21:34:53 +05:30
Sojan JoseandGitHub 4f83d5451e Chore: Routine Bugfixes and enhancements (#979)
- Fix slack scopes
- Docs for authentication
Fixes: #704 , #973
2020-06-25 23:35:16 +05:30
Pranav Raj SandGitHub 0aab717bb3 Chore: Add default value for label color (#981) 2020-06-25 21:33:56 +05:30
97ad39713b Feature: Improve label experience (#975)
Co-authored-by: Sojan <sojan@pepalo.com>
2020-06-25 21:04:03 +05:30
Pranav Raj SandGitHub 8b61452d56 Chore: Fix typo in Slack documentation (#977)
- Fix typo in slack-integration-setup.md
2020-06-22 13:40:31 +05:30
1ef8d03e18 Feature: Slack - receive messages, create threads, send replies (#974)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-06-22 13:19:26 +05:30
Sojan aa8a85b8bd Merge branch 'hotfix/1.5.3' into develop 2020-06-22 12:02:58 +05:30
Sojan 77c16932f8 Merge branch 'hotfix/1.5.3' 2020-06-22 12:02:50 +05:30
Sojan d4214cd78f Bugfix: Invalid argument expiry in global config
references: #976
2020-06-22 12:01:26 +05:30
963f173730 Feature: ResizableTextArea in widget and dashboard (#969)
* Create ResizableTextArea component
* Rubocop fixes and spec fixes

Co-authored-by: Sojan <sojan@pepalo.com>
2020-06-18 15:17:45 +05:30
Sojan JoseandGitHub 04f6460afb Chore: Fix failing sidekiq events for contact create (#966) 2020-06-16 19:39:57 +05:30
b0bbd757b5 Chore: FCM Notification Improvements (#957)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-06-15 13:36:56 +05:30
Pranav Raj SandGitHub 667e3abbe1 Fix: Set widget bg color for file-bubble (#965) 2020-06-15 13:35:52 +05:30
Pranav Raj SandGitHub 7c6ea3a05a Chore: Fix HTML rendering in ConversationCard (#963) 2020-06-14 18:30:36 +05:30
Pranav Raj SandGitHub 5cb88237f5 Chore: Move conversationStats to a seperate module (#962)
* Chore: Move conversationStats to a seperate module

* Move toggleTyping to conversationTypingStatus

* Remove unused agentTyping flag

* Fix review comments
2020-06-14 14:07:52 +05:30
Nithin David ThomasandGitHub 5ec9af9325 Bug: Add min height to widget input box (#960) 2020-06-14 11:28:38 +05:30
Pranav Raj SandGitHub ecd5e20133 Bug: Replace non-numeric characters in Twilio phonenumber (#958) 2020-06-13 22:29:12 +05:30
944fbf27b7 Enhancement: Improve scrolling on widget #954 (#955)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-06-13 20:33:23 +05:30
f9e8bb8e10 Chore: Send browser language in webwidget events (#952)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-06-13 00:19:43 +05:30
Subin T PandGitHub ed1c871633 Feature: Slack integration (#783)
- Integrations architecture
- Slack integration
2020-06-12 23:12:47 +05:30
Pranav Raj SandGitHub 4f3b483066 Chore: Add Github Sponsors link 2020-06-12 19:37:00 +05:30
ca7554f88c Chore: Add deployment documentation (#904)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-06-11 22:34:22 +05:30
Pranav Raj SandGitHub e769282e7f BugFix: Fix missing tagline in inbox settings (#949) 2020-06-10 00:30:37 +05:30
Sojan 3823ad8fef Merge branch 'master' into develop 2020-06-10 00:25:52 +05:30
Sojan 04a0aa5f1b BugFix: Fix twitter DM view
- Fix twitter DMs gettings getting appended to tweet conversation

Fixes: #939
2020-06-10 00:25:05 +05:30
Sojan 991648edcf Merge branch 'hotfix/1.5.2' 2020-06-10 00:24:12 +05:30
Sojan bfe10618fb BugFix: Fix twitter DM view
- Fix twitter DMs gettings getting appended to tweet conversation

Fixes: #939
2020-06-10 00:23:34 +05:30
Pranav Raj SandGitHub eadc33d230 Use empty string as fallback greeting_message if null (#948) 2020-06-10 00:16:34 +05:30
432dad203b Feature: Inbox greeting message (#927)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-06-09 23:54:35 +05:30
Sojan JoseandGitHub 8b022311c0 Chore: FCM Push Fixes (#934) 2020-06-09 17:42:18 +05:30
Pranav Raj SandGitHub 40481f6462 Bugfix: Update conversation counters in realtime (#944)
* Bug: Update conversation counters in realtime
2020-06-09 16:26:33 +05:30
Pranav Raj SandGitHub 602132119b Fix socket reconnect if the pubsub token is same (#942) 2020-06-08 19:13:33 +05:30
Sojan JoseandGitHub 52d28105e4 Chore: Remove dead code related to billing (#935)
- remove subscription model
- remove billing-related code
2020-06-07 20:31:48 +05:30
Sojan JoseandGitHub 051871a3cd Chore: Code Cleanup in API controllers (#932)
* Chore: Code Cleanup in API controllers

* Remove unnecessary scoping for accounts controller
2020-06-07 13:58:05 +05:30
Sojan JoseandGitHub 3d84568a37 Feature: Label APIs (#931) 2020-06-07 11:17:13 +05:30
Sojan JoseandGitHub 915eefdc36 Bugfix: FCM push subscription builder fix (#930) 2020-06-06 20:53:30 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ede4dd9cb0 Chore: Bump websocket-extensions from 0.1.3 to 0.1.4 (#929)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-06 18:56:58 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b7f7b54f9b Chore: Bump websocket-extensions from 0.1.4 to 0.1.5 (#928)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-ruby) from 0.1.4 to 0.1.5.
- [Release notes](https://github.com/faye/websocket-extensions-ruby/releases)
- [Changelog](https://github.com/faye/websocket-extensions-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-ruby/compare/0.1.4...0.1.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-06 15:56:54 +05:30
Sojan JoseandGitHub a13a474c23 Chore: Firebase Cloud Messaging Support (#858) 2020-06-05 00:15:50 +05:30
Sojan e783c3af5d Merge branch 'release/1.5.1' 2020-06-04 23:15:08 +05:30
68be7e3ea8 Use db:prepare instead of db:migrate (#924)
Use db:prepare instead of db:migrate

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-06-04 23:13:10 +05:30
Koichi MATSUMOTOandGitHub 72a25ffdc5 BugFix: Fix undefined method compare_and_save (#921)
Fix undefined method `compare_and_save` in config loader
2020-06-04 22:33:10 +05:30
Sojan 89dafa366e Merge branch 'release/1.5.0' 2020-06-02 23:53:19 +05:30
Sojan JoseandGitHub dafabac796 Chore: Minor bugfixes and housekeeping tasks (#896) 2020-06-02 23:50:39 +05:30
Sojan JoseandGitHub 93d8a25877 Enable Spanish (#913) 2020-06-02 23:43:03 +05:30
f78df91dd2 Chore: Contact Sidebar, conversation cleanup (#908)
- Update sidebar design
- Move every contact data to contacts module
- Revert go to next conversation feature
- Fix issues with new conversation in action cable
- Escape HTML content
- Broadcast event when conversation.contact changes.

Co-authored-by: Sojan <sojan@pepalo.com>
2020-06-02 22:59:02 +05:30
Sojan JoseandGitHub 8c52a3a953 Chore: Remove duplication of user JBuilder (#911)
* Chore: Reduce duplication of user JBuilder
2020-05-31 23:10:20 +05:30
Pranav Raj SandGitHub d4783db6fd Chore: Update app logo, add FRONTEND_URL env var (#910)
Chore: Update app logo, add FRONTEND_URL env var
2020-05-31 21:49:28 +05:30
Pranav Raj SandGitHub 586c616ae3 Bug: Render header title and tagline as HTML (#906)
* Render header title and tagline as HTML
2020-05-31 16:35:10 +05:30
Pranav Raj SandGitHub 884a1c5971 Chore: Add an option to upload a business logo to inbox (#905)
Chore: Add an option to upload a business logo to inbox
2020-05-31 16:16:22 +05:30
Pranav Raj SandGitHub 47ec7ad7c9 Feature: Ability to customise widget color (#903)
- Use Chrome style color-picker
2020-05-30 17:28:00 +05:30
Pranav Raj SandGitHub ec197b077d Chore: Add db migrate to Heroku release phase (#901) 2020-05-29 14:53:27 +05:30
Ronald WalkerandGitHub 10a1758261 Bug: Fix false positive in #toggleAgentTypingStatus spec (#899) 2020-05-29 12:37:18 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a9d93b750c Chore: Bump kaminari from 1.2.0 to 1.2.1 (#898)
Bumps [kaminari](https://github.com/kaminari/kaminari) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/kaminari/kaminari/releases)
- [Changelog](https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kaminari/kaminari/compare/v1.2.0...v1.2.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-05-29 11:14:27 +05:30
Pranav Raj SandGitHub efc59bb43f Bug: Fix account_id in URLs (#894)
* Bug: Fix account_id in URLs
* Fix accountMixin specs
2020-05-26 23:36:42 +05:30
b7a583b2c4 Feature: Ability to switch between multiple accounts (#881)
* Feature: Ability to switch between multiple accounts

* Fix rubocop

* Fix assigned inboxes

* fix auth json

* Add account switcher in UI

* fix ordering on administrate

* Add switch accounts to sidebar

* add account id

* Fix schema.rb timestamp

* Revert "add account id"

This reverts commit 27570f50ef584cb9a5f69454f43f630b318c8807.

* Add a check for account

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-05-26 22:38:48 +05:30
Abdulkadir PoyrazandGitHub b1aab228ae Feature: Ability to mute contacts (#891)
fixes: #867
2020-05-26 17:43:59 +05:30
Sojan JoseandGitHub d8d14fc4a4 Feature: Rewamp super admin dashboard (#882) 2020-05-24 22:44:26 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e49a200ee0 Chore: Bump puma from 4.3.4 to 4.3.5 (#890)
Bumps [puma](https://github.com/puma/puma) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-05-23 14:21:13 +05:30
Jean TraulléandGitHub 8ccc00b5ba Add crowdin badge on README.md (#889) 2020-05-22 19:59:26 +05:30
Sony MathewandGitHub 6230f4d796 Enhancement: Threaded email replies for a conversation (#885) (#886)
* Added custom Message-ID and In-Reply-To headers for conversation reply emails
* Added new global config for the default domain (This is used in the above headers)
* Added migration to run the config loader to load the new global config value
* The subject of the conversation reply mailer was made static (This is required for threaded emails)
* Added required tests
2020-05-22 18:14:18 +05:30
Sony MathewandGitHub 11b4b4ea3f Chore: Parse quoted text in incoming emails (#883) (#884)
* Chore: Parse quoted text in incoming emails (#883)
* Parsed the quoted text and replies in incoming emails and store them separately
* Did this parsing for plain text and html part of emails
* In the chat window, we will only show the parsed reply alone

* Conversation mailbox test fixes (#883)
2020-05-22 18:07:06 +05:30
Sony MathewandGitHub 00093fa408 Fixed rspec due to unescaped html check for user name (#887) (#888)
* Fixed the flaky failure in rspec for super admin user controller due to unescaped user name check
2020-05-22 17:58:08 +05:30
Sojan JoseandGitHub f6a9f791cf Chore: Configure Letter opener with environment variable (#880) 2020-05-20 20:02:28 +05:30
Pranav Raj SandGitHub 8af200ad20 Fix missing translations, enable dutch language (#878)
* Fix missing translations, enable dutch language
2020-05-19 19:05:10 +05:30
Pranav Raj SandGitHub 3f5ce2ddbf Bug: Fix autoload_paths for facebook bot (#877)
* Fix autoload_paths for facebook bot
2020-05-18 15:32:26 +05:30
6e92d9be9e Bug: Fix Facebook v7.0 API issues (#863)
* Fix v7.0 API issues

Co-authored-by: Sojan <sojan@pepalo.com>
2020-05-17 23:44:50 +05:30
Pranav Raj SandGitHub b7129785c6 Chore: View form responses as user messages (#876)
* Chore: View form responses as user messages
2020-05-17 22:49:45 +05:30
Pranav Raj SandGitHub 246d0b407f Chore: UI Cleanup in modals (#873)
* Chore: UI Cleanup in modals

* Fix review comments
2020-05-17 21:07:45 +05:30
59f4dd7ebe Feature: Introduce locale in web-widget SDK (#871)
* Introduce setLocale in SDK

Co-authored-by: Sojan <sojan@pepalo.com>
2020-05-17 16:15:53 +05:30
Sojan JoseandGitHub 2e8cd59a06 Add new translations (#862)
* New translations agentMgmt.json (Dutch)

* New translations login.json (Dutch)

* New translations settings.json (French)

* New translations en.json (French)

* New translations en.json (Arabic)

* New translations en.json (Greek)

* New translations settings.json (Portuguese, Brazilian)

* New translations settings.json (Dutch)

* New translations settings.json (Greek)

* New translations signup.json (Ukrainian)

* New translations chatlist.json (Dutch)

* New translations contact.json (Dutch)

* New translations billing.json (Dutch)

* New translations cannedMgmt.json (Dutch)

* New translations inboxMgmt.json (Dutch)

* New translations conversation.json (Dutch)

* New translations generalSettings.json (Dutch)

* New translations en.json (Dutch)

* New translations en.json (Portuguese, Brazilian)

* New translations devise.en.yml (Dutch)

* New translations en.yml (Dutch)
2020-05-16 18:07:19 +05:30
Pranav Raj SandGitHub 467fcda6fc Chore: Add docs for push notifications env (#865) 2020-05-15 12:15:28 +05:30
Sojan JoseandGitHub e6aa851987 Chore: Add Account Users to Admin Panel (#859)
- Show errors on login page
- Dashboard for admin panel
2020-05-14 22:51:51 +05:30
20f39caa42 Chore: Twitter Integration house cleaning (#855)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-05-14 22:51:07 +05:30
Bruno AlmeidaandGitHub 1108446974 Feature: Move to the next conversation when I resolve a the current c… (#757)
* Feature: Move to the next conversation when I resolve a the current conversation

* check if nextId is present before emitting the event

* use es6 string literals

* use a named variable for better reading

* create a variable for better readability

* better sintax to get clickable element

* after last, go to first chat when resolve

* use state and action to set next chat

* remove not used emit

* clear selected state when there is not next chat

* Remove deprecated scope from FB Channel (#761)

Remove deprecated scope from FB Channel

* Feature: Customise the position of messenger (#767)

Co-authored-by: Nithin David Thomas <webofnithin@gmail.com>

* Bug: Redirect user to set new password screen (#772)

* auto linter

* fix js linter

* sort chats on getter / filter before getting next chat

* Revert not related changes on ConversationCard.vue

* add test for getNextChatConversation getter

* remove not used module

* add test for getAllConversations getter
2020-05-14 13:43:02 +05:30
Ronald WalkerandGitHub e6bf81caf4 Bug: Fix widget icon alignment in Firefox (#857) 2020-05-14 11:42:53 +05:30
005f332776 Chore: Fixed auto-generated German translations
"canned responses" are no food: "Eingemachte Antwort" -> "Vorgefertigte Antwort"
"open", "closed" status are no verbs, so "Öffnen" -> "Offen", ...
"mine" has nothing to do with mining :) "Bergwerk" -> "Meine"
"home" isn't your home, but the main page "Hauptseite"
"resolve action" is about solutions, not determination, so
"Entschlossenheit" -> "Fall schließen"
"settings" are simply "Einstellungen"

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-05-13 22:47:31 +05:30
Pranav Raj SandGitHub d219b0a45e Chore: Add an option to toggle web manifest (#848) 2020-05-12 12:45:28 +05:30
f819bc0f33 Chore: Use installation config in frontend (#847)
* Use installation config in widget
* Add configuration for installation in UI
* Add config for mailer

Co-authored-by: Sojan <sojan@pepalo.com>
2020-05-12 01:31:40 +05:30
c74b5c21d7 Feature: Introduce Super Admins (#705)
* Feature: Introduce Super Admins

- added new devise model for super user
- added administrate gem
- sample dashboards for users and accounts

Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-05-11 23:07:22 +05:30
Sony MathewandGitHub 8859880e55 Feature: Global Config helper (#844) (#845)
* Added a global config helper to easily access installation/global configs
  * this will fetch the keys from cache with fallback to DB on cache miss
  * ability to query multiple keys simultaneously
  * interface to delete the existing global config cache
* Added tests for this new helper module
2020-05-11 19:00:33 +05:30
Pranav Raj Sreepuram 6e0f02a38b Merge branch 'hotfix/1.4.2' into develop 2020-05-11 11:43:49 +05:30
Sony MathewandGitHub 905c93b8f8 Feature: Installation global config (#839) (#840)
* Renamed concern from Feature to Featurable

* Feature: Installation config (#839)
* Added new model installtion config with corresponding migrations and specs
* Created an installation config yml (key value store model)
* Created a config loader module to load the installaltion configs
* Added this to the config loader seeder
* Changed the account before create hook for default feature enabling to use the feature values from installtion config
* Renamed the feature concern to Featurable to follow the naming pattern for concerns
* Added comments and specs for modules and places that deemed necessary

* Refactored config loader to reduce cognitive complexity (#839)
2020-05-10 22:40:36 +05:30
Pranav Raj SandGitHub 76b98cbed4 Bug: Fix inbox.agent_bot nil case (#841) 2020-05-10 22:20:45 +05:30
sony-mathew dedbe08a1c Hotfix: Fixed private notes in email notifications - Merge branch 'master' into develop 2020-05-10 16:38:55 +05:30
sony-mathew a5cc3bae6c Hotfix: Fix for private note in conversation email notifications - Merge branch 'hotfix/1.4.1' into develop 2020-05-10 16:22:53 +05:30
Pranav Raj SandGitHub f28ec29b8c Feature: Customise widget for bot conversations (#834)
* Feature: Customise widget for bot conversations
2020-05-09 22:02:43 +05:30
Sojan JoseandGitHub 05ea6308f2 Chore: Update ruby and rails versions (#831) 2020-05-08 12:13:23 +05:30
2043 changed files with 90442 additions and 13711 deletions
+17 -15
View File
@@ -7,7 +7,7 @@ defaults: &defaults
working_directory: ~/build
docker:
# specify the version you desire here
- image: circleci/ruby:2.7.0-node-browsers
- image: circleci/ruby:2.7.2-node-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
@@ -16,7 +16,7 @@ defaults: &defaults
- image: circleci/redis:alpine
environment:
- CC_TEST_REPORTER_ID: b1b5c4447bf93f6f0b06a64756e35afd0810ea83649f03971cbf303b4449456f
- RAILS_LOG_TO_STDOUT: false
jobs:
build:
<<: *defaults
@@ -69,11 +69,11 @@ jobs:
- run:
name: Download cc-test-reporter
command: |
mkdir -p tmp/
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./tmp/cc-test-reporter
chmod +x ./tmp/cc-test-reporter
mkdir -p ~/tmp
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ~/tmp/cc-test-reporter
chmod +x ~/tmp/cc-test-reporter
- persist_to_workspace:
root: tmp
root: ~/tmp
paths:
- cc-test-reporter
@@ -98,10 +98,10 @@ jobs:
- run:
name: Run backend tests
command: |
bundle exec rspec $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
./tmp/cc-test-reporter format-coverage -t simplecov -o tmp/codeclimate.backend.json coverage/backend/.resultset.json
bundle exec rspec $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) --profile=10
~/tmp/cc-test-reporter format-coverage -t simplecov -o ~/tmp/codeclimate.backend.json coverage/backend/.resultset.json
- persist_to_workspace:
root: tmp
root: ~/tmp
paths:
- codeclimate.backend.json
@@ -109,21 +109,23 @@ jobs:
name: Run frontend tests
command: |
yarn test:coverage
./tmp/cc-test-reporter format-coverage -t lcov -o tmp/codeclimate.frontend.json buildreports/lcov.info
~/tmp/cc-test-reporter format-coverage -t lcov -o ~/tmp/codeclimate.frontend.json buildreports/lcov.info
- persist_to_workspace:
root: tmp
root: ~/tmp
paths:
- codeclimate.frontend.json
# collect reports
- store_test_results:
path: /tmp/test-results
path: ~/tmp/test-results
- store_artifacts:
path: /tmp/test-results
path: ~/tmp/test-results
destination: test-results
- store_artifacts:
path: log
- run:
name: Upload coverage results to Code Climate
command: |
./tmp/cc-test-reporter sum-coverage tmp/codeclimate.*.json -p 2 -o tmp/codeclimate.total.json
./tmp/cc-test-reporter upload-coverage -i tmp/codeclimate.total.json
~/tmp/cc-test-reporter sum-coverage ~/tmp/codeclimate.*.json -p 2 -o ~/tmp/codeclimate.total.json
~/tmp/cc-test-reporter upload-coverage -i ~/tmp/codeclimate.total.json
+51
View File
@@ -0,0 +1,51 @@
# pre-build stage
ARG VARIANT=2.7
FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}
# Update args in docker-compose.yaml to set the UID/GID of the "vscode" user.
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
groupmod --gid $USER_GID vscode \
&& usermod --uid $USER_UID --gid $USER_GID vscode \
&& chmod -R $USER_UID:$USER_GID /home/vscode; \
fi
# [Option] Install Node.js
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
# tmux is for overmind
# TODO : install foreman in future
# packages: postgresql-server-dev-all
# may be postgres in same machine
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends \
libssl-dev \
tar \
tzdata \
postgresql-client \
yarn \
git \
imagemagick \
tmux \
zsh
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
# Do the set up required for chatwoot app
WORKDIR /workspace
COPY . /workspace
# TODO: figure out installing rvm
# RUN rvm install
COPY Gemfile Gemfile.lock ./
RUN gem install bundler
RUN bundle install
COPY package.json yarn.lock ./
RUN yarn install
+33
View File
@@ -0,0 +1,33 @@
{
"name": "Chatwoot Development Codespace",
"service": "app",
"dockerComposeFile": "docker-compose.yml",
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"rebornix.Ruby",
"misogi.ruby-rubocop",
"wingrunr21.vscode-ruby"
],
// TODO: figure whether we can get all this ports work properly
// 3000 rails
// 3035 webpacker
// 5432 postgres
// 6379 redis
// 1025,8025 mailhog
"forwardPorts": [5432, 6379, 1025, 8025],
//your application may need to listen on all interfaces (0.0.0.0) not just localhost for it to be available externally. Defaults to []
"appPort": [3000, 3035],
// Use 'postCreateCommand' to run commands after the container is created.
// #TODO: can we move logic of copy env file into dockerfile ?
"postCreateCommand": "cp .env.example .env",
}
+56
View File
@@ -0,0 +1,56 @@
# https://github.com/microsoft/vscode-dev-containers/blob/master/containers/python-3-postgres/.devcontainer/docker-compose.yml
# https://github.com/microsoft/vscode-dev-containers/blob/master/containers/ruby-rails/.devcontainer/devcontainer.json
#
version: '3'
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
# Update 'VARIANT' to pick a Ruby version: 2, 2.7, 2.6, 2.5
VARIANT: 2.7
# [Choice] Install Node.js
INSTALL_NODE: "true"
NODE_VERSION: "lts/*"
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
USER_UID: 1000
USER_GID: 1000
volumes:
- ..:/workspace:cached
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db
db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres
redis:
image: redis:latest
restart: unless-stopped
network_mode: service:db
volumes:
- redis-data:/data
mailhog:
restart: unless-stopped
image: mailhog/mailhog
network_mode: service:db
volumes:
postgres-data:
redis-data:
+65 -25
View File
@@ -4,6 +4,13 @@ SECRET_KEY_BASE=replace_with_lengthy_secure_hex
# Replace with the URL you are planning to use for your app
FRONTEND_URL=http://0.0.0.0:3000
# If the variable is set, all non-authenticated pages would fallback to the default locale.
# Whenever a new account is created, the default language will be DEFAULT_LOCALE instead of en
# DEFAULT_LOCALE=en
# If you plan to use CDN for your assets, set Asset CDN Host
ASSET_CDN_HOST=
# Force all access to the app over SSL, default is set to false
FORCE_SSL=false
@@ -11,7 +18,7 @@ FORCE_SSL=false
# true : default option, allows sign ups
# false : disables all the end points related to sign ups
# api_only: disables the UI for signup, but you can create sign ups via the account apis
ENABLE_ACCOUNT_SIGNUP=true
ENABLE_ACCOUNT_SIGNUP=false
# Redis config
REDIS_URL=redis://redis:6379
@@ -19,6 +26,11 @@ REDIS_URL=redis://redis:6379
# which will be the password for the redis service running inside the docker-compose
# to make it secure
REDIS_PASSWORD=
# Redis Sentinel can be used by passing list of sentinel host and ports e,g. sentinel_host1:port1,sentinel_host2:port2
REDIS_SENTINELS=
# Redis sentinel master name is required when using sentinel, default value is "mymaster".
# You can find list of master using "SENTINEL masters" command
REDIS_SENTINEL_MASTER_NAME=
# Postgres Database config variables
POSTGRES_HOST=postgres
@@ -27,27 +39,35 @@ POSTGRES_PASSWORD=
RAILS_ENV=development
RAILS_MAX_THREADS=5
# Mail outgoing
MAILER_SENDER_EMAIL=accounts@chatwoot.com
SMTP_PORT=1025
# The email from which all outgoing emails are sent
# could user either `email@yourdomain.com` or `BrandName <email@yourdomain.com>`
MAILER_SENDER_EMAIL=Chatwoot <accounts@chatwoot.com>
#SMTP domain key is set up for HELO checking
SMTP_DOMAIN=chatwoot.com
# if you are running docker-compose, set SMTP_ADDRESS value as "mailhog",
# else set the value as "localhost"
# the default value is set "mailhog" and is used by docker-compose for development environments,
# Set the value as "localhost" or your SMTP address in other environments
SMTP_ADDRESS=mailhog
SMTP_PORT=1025
SMTP_USERNAME=
SMTP_PASSWORD=
# plain,login,cram_md5
SMTP_AUTHENTICATION=
SMTP_ENABLE_STARTTLS_AUTO=
SMTP_ENABLE_STARTTLS_AUTO=true
# Can be: 'none', 'peer', 'client_once', 'fail_if_no_peer_cert', see http://api.rubyonrails.org/classes/ActionMailer/Base.html
SMTP_OPENSSL_VERIFY_MODE=peer
# Mail Incoming
# This is the domain set for the reply emails when conversation continuity is enabled
MAILER_INBOUND_EMAIL_DOMAIN=
# Set this to appropriate ingress channel with regards to incoming emails
# Possible values are :
# :relay for Exim, Postfix, Qmail
# :mailgun for Mailgun
# :mandrill for Mandrill
# :postmark for Postmark
# :sendgrid for Sendgrid
# relay for Exim, Postfix, Qmail
# mailgun for Mailgun
# mandrill for Mandrill
# postmark for Postmark
# sendgrid for Sendgrid
RAILS_INBOUND_EMAIL_SERVICE=
# Use one of the following based on the email ingress service
# Ref: https://edgeguides.rubyonrails.org/action_mailbox_basics.html
@@ -59,6 +79,7 @@ MANDRILL_INGRESS_API_KEY=
ACTIVE_STORAGE_SERVICE=local
# Amazon S3
# documentation: https://www.chatwoot.com/docs/configuring-s3-bucket-as-cloud-storage
S3_BUCKET_NAME=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
@@ -73,36 +94,55 @@ RAILS_LOG_TO_STDOUT=true
LOG_LEVEL=info
LOG_SIZE=500
# Credentials to access sidekiq dashboard in production
SIDEKIQ_AUTH_USERNAME=
SIDEKIQ_AUTH_PASSWORD=
### This environment variables are only required if you are setting up social media channels
#facebook
# Facebook
# documentation: https://www.chatwoot.com/docs/facebook-setup
FB_VERIFY_TOKEN=
FB_APP_SECRET=
FB_APP_ID=
# Twitter
# documentation: https://www.chatwoot.com/docs/twitter-app-setup
TWITTER_APP_ID=
TWITTER_CONSUMER_KEY=
TWITTER_CONSUMER_SECRET=
TWITTER_ENVIRONMENT=
#slack integration
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
### Change this env variable only if you are using a custom build mobile app
## Mobile app env variables
IOS_APP_ID=6C953F3RX2.com.chatwoot.app
#### This environment variables are only required in hosted version which has billing
ENABLE_BILLING=
## chargebee settings
CHARGEBEE_API_KEY=
CHARGEBEE_SITE=
CHARGEBEE_WEBHOOK_USERNAME=
CHARGEBEE_WEBHOOK_PASSWORD=
### Smart App Banner
# https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
# You can find your app-id in https://itunesconnect.apple.com
#IOS_APP_IDENTIFIER=1495796682
## Push Notification
## generate a new key value here : https://d3v.one/vapid-key-generator/
# VAPID_PUBLIC_KEY=
# VAPID_PRIVATE_KEY=
#
# for mobile apps
# FCM_SERVER_KEY=
## Bot Customizations
USE_INBOX_AVATAR_FOR_BOT=true
## IP look up configuration
## ref https://github.com/alexreisner/geocoder/blob/master/README_API_GUIDE.md
## works only on accounts with ip look up feature enabled
# IP_LOOKUP_SERVICE=geoip2
# maxmindb api key to use geoip2 service
# IP_LOOKUP_API_KEY=
## Development Only Config
# if you want to use letter_opener for local emails
# LETTER_OPENER=true
+1
View File
@@ -46,5 +46,6 @@ module.exports = {
},
globals: {
__WEBPACK_ENV__: true,
bus: true,
},
};
+1
View File
@@ -1 +1,2 @@
open_collective: chatwoot
github: chatwoot
+18 -2
View File
@@ -2,15 +2,16 @@
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
labels: 'Bug'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
@@ -18,11 +19,25 @@ Steps to reproduce the behavior:
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Browser logs**
Share the browser logs to debug the issue further
**Server logs**
Share the server logs to debug the issue further
**Environment**
Describe whether you are using Chatwoot Cloud (app.chatwoot.com) or a self hosted installation of Chatwoot. If you are using a self hosted installation of Chatwoot describe the type of deployment (Docker/Linux VM installation/Heroku)
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
@@ -35,4 +50,5 @@ If applicable, add screenshots to help explain your problem.
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+2 -2
View File
@@ -24,9 +24,9 @@ Please describe the tests that you ran to verify your changes. Provide instructi
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have commented on my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
- [ ] Any dependent changes have been merged and published in downstream modules
+9 -1
View File
@@ -16,6 +16,7 @@
/tmp/*
!/log/.keep
!/tmp/.keep
*.mmdb
# Ignore Byebug command history file.
.byebug_history
@@ -23,7 +24,7 @@
*.log
# Ignore application configuration
node_modules
master.key
*.rdb
# Ignore env files
@@ -55,3 +56,10 @@ node_modules
package-lock.json
*.dump
# cypress
test/cypress/videos/*
/config/master.key
/config/*.enc
+34 -12
View File
@@ -4,32 +4,40 @@ require:
- rubocop-rspec
inherit_from: .rubocop_todo.yml
Lint/RaiseException:
Enabled: true
Lint/StructNewOverride:
Enabled: true
Layout/LineLength:
Max: 150
Metrics/ClassLength:
Max: 125
Exclude:
- 'app/models/conversation.rb'
- 'app/mailers/conversation_reply_mailer.rb'
- 'app/models/message.rb'
RSpec/ExampleLength:
Max: 25
Style/Documentation:
Enabled: false
Style/ExponentialNotation:
Enabled: false
Style/FrozenStringLiteralComment:
Enabled: false
Style/SymbolArray:
Enabled: false
Style/HashEachMethods:
Enabled: true
Style/HashTransformKeys:
Enabled: true
Style/HashTransformValues:
Enabled: true
Style/OptionalBooleanParameter:
Exclude:
- 'app/services/email_templates/db_resolver_service.rb'
- 'app/dispatchers/dispatcher.rb'
Style/GlobalVars:
Exclude:
- 'config/initializers/redis.rb'
- 'lib/redis/alfred.rb'
- 'lib/global_config.rb'
Style/ClassVars:
Exclude:
- 'app/services/email_templates/db_resolver_service.rb'
Lint/MissingSuper:
Exclude:
- 'app/drops/base_drop.rb'
Metrics/BlockLength:
Exclude:
- spec/**/*
@@ -42,6 +50,7 @@ Rails/ApplicationController:
- 'app/controllers/dashboard_controller.rb'
- 'app/controllers/widget_tests_controller.rb'
- 'app/controllers/widgets_controller.rb'
- 'app/controllers/platform_controller.rb'
Style/ClassAndModuleChildren:
EnforcedStyle: compact
Exclude:
@@ -62,12 +71,14 @@ Style/GuardClause:
- 'app/builders/account_builder.rb'
- 'app/models/attachment.rb'
- 'app/models/message.rb'
- 'lib/webhooks/chargebee.rb'
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Metrics/AbcSize:
Exclude:
- 'app/controllers/concerns/auth_helper.rb'
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
- 'db/migrate/20161123131628_devise_token_auth_create_users.rb'
Metrics/CyclomaticComplexity:
Max: 7
Exclude:
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Rails/ReversibleMigration:
@@ -94,15 +105,26 @@ Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/channel/twitter_profile.rb'
- 'app/models/webhook.rb'
Rails/RenderInline:
Exclude:
- 'app/controllers/swagger_controller.rb'
RSpec/NamedSubject:
Enabled: false
# we should bring this down
RSpec/MultipleMemoizedHelpers:
Max: 12
AllCops:
NewCops: enable
Exclude:
- 'bin/**/*'
- 'db/schema.rb'
- 'config/**/*'
- 'public/**/*'
- 'config/initializers/bot.rb'
- 'vendor/**/*'
- 'node_modules/**/*'
- 'lib/tasks/auto_annotate_models.rake'
- 'config/environments/**/*'
- 'tmp/**/*'
- 'storage/**/*'
- 'db/migrate/20200225162150_init_schema.rb'
- 'config/initializers/azure_storage_service_patch.rb'
-28
View File
@@ -6,13 +6,6 @@
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 1
# Configuration parameters: EnforcedStyle.
# SupportedStyles: native, lf, crlf
Layout/EndOfLine:
Exclude:
- 'deploy/after_restart.rb'
# Offense count: 1
Lint/DuplicateMethods:
Exclude:
@@ -88,7 +81,6 @@ Naming/MemoizedInstanceVariableName:
- 'app/controllers/application_controller.rb'
- 'app/models/message.rb'
- 'lib/integrations/widget/outgoing_message_builder.rb'
- 'lib/webhooks/chargebee.rb'
# Offense count: 4
# Cop supports --auto-correct.
@@ -187,7 +179,6 @@ Rails/EnumHash:
- 'app/models/attachment.rb'
- 'app/models/conversation.rb'
- 'app/models/message.rb'
- 'app/models/subscription.rb'
- 'app/models/user.rb'
# Offense count: 1
@@ -226,7 +217,6 @@ Rails/Output:
Rails/TimeZone:
Exclude:
- 'app/builders/report_builder.rb'
- 'app/models/subscription.rb'
- 'lib/reports/update_account_identity.rb'
- 'lib/reports/update_agent_identity.rb'
- 'lib/reports/update_identity.rb'
@@ -269,24 +259,6 @@ Style/CommentedKeyword:
- 'app/controllers/api/v1/conversations/labels_controller.rb'
- 'app/controllers/api/v1/labels_controller.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle.
# SupportedStyles: annotated, template, unannotated
Style/FormatStringToken:
Exclude:
- 'lib/constants/redis_keys.rb'
# Offense count: 4
# Configuration parameters: AllowedVariables.
Style/GlobalVars:
Exclude:
- 'lib/redis/alfred.rb'
# Offense count: 4
Style/IdenticalConditionalBranches:
Exclude:
- 'app/controllers/api/v1/reports_controller.rb'
# Offense count: 1
# Configuration parameters: AllowIfModifier.
Style/IfInsideElse:
+1 -1
View File
@@ -1 +1 @@
2.7.0
2.7.2
+5 -1
View File
@@ -51,7 +51,7 @@ linters:
ElsePlacement:
enabled: true
style: same_line # or 'new_line'
style: new_line
EmptyLineBetweenBlocks:
enabled: true
@@ -177,6 +177,8 @@ linters:
allow_element_with_attribute: false
allow_element_with_class: false
allow_element_with_id: false
exclude:
- 'app/assets/stylesheets/administrate/components/_buttons.scss'
SelectorDepth:
enabled: true
@@ -279,3 +281,5 @@ linters:
exclude:
- 'app/javascript/widget/assets/scss/_reset.scss'
- 'app/javascript/widget/assets/scss/sdk.css'
- 'app/assets/stylesheets/administrate/reset/_normalize.scss'
- 'app/javascript/shared/assets/stylesheets/*.scss'
+46 -13
View File
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
ruby '2.7.0'
ruby '2.7.2'
##-- base gems for rails --##
gem 'rack-cors', require: 'rack/cors'
@@ -8,7 +8,7 @@ gem 'rails'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', require: false
##-- rails helper gems --##
##-- rails application helper gems --##
gem 'acts-as-taggable-on'
gem 'attr_extras'
gem 'browser'
@@ -23,6 +23,14 @@ gem 'tzinfo-data'
gem 'valid_email2'
# compress javascript config.assets.js_compressor
gem 'uglifier'
##-- used for single column multiple binary flags in notification settings/feature flagging --##
gem 'flag_shih_tzu'
# Random name generator for user names
gem 'haikunator'
# Template parsing safely
gem 'liquid'
# Parse Markdown to HTML
gem 'commonmarker'
##-- for active storage --##
gem 'aws-sdk-s3', require: false
@@ -36,12 +44,16 @@ gem 'pg'
gem 'redis'
gem 'redis-namespace'
gem 'redis-rack-cache'
# super fast record imports in bulk
gem 'activerecord-import'
##--- gems for server & infra configuration ---##
gem 'dotenv-rails'
gem 'foreman'
gem 'puma'
gem 'webpacker'
gem 'webpacker', '~> 5.x'
# metrics on heroku
gem 'barnes'
##--- gems for authentication & authorization ---##
gem 'devise'
@@ -49,24 +61,25 @@ gem 'devise_token_auth'
# authorization
gem 'jwt'
gem 'pundit'
# super admin
gem 'administrate'
##--- gems for pubsub service ---##
# https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/
gem 'wisper', '2.0.0'
##--- gems for billing ---##
gem 'chargebee'
##--- gems for channels ---##
gem 'facebook-messenger'
# TODO: bump up gem to 2.0
gem 'facebook-messenger', '1.5.0'
gem 'telegram-bot-ruby'
gem 'twilio-ruby', '~> 5.32.0'
# twitty will handle subscription of twitter account events
gem 'twitty', git: 'https://github.com/chatwoot/twitty'
# gem 'twitty', git: 'https://github.com/chatwoot/twitty'
gem 'twitty'
# facebook client
gem 'koala'
# Random name generator
gem 'haikunator'
# slack client
gem 'slack-ruby-client'
##--- gems for debugging and error reporting ---##
# static analysis
@@ -76,13 +89,22 @@ gem 'sentry-raven'
##-- background job processing --##
gem 'sidekiq'
##-- used for single column multiple binary flags in notification settings/feature flagging --##
gem 'flag_shih_tzu'
# We want cron jobs
gem 'sidekiq-cron'
##-- Push notification service --##
gem 'fcm'
gem 'webpush'
##-- geocoding / parse location from ip --##
# http://www.rubygeocoder.com/
gem 'geocoder'
# to parse maxmind db
gem 'maxminddb'
# to create db triggers
gem 'hairtrigger'
group :development do
gem 'annotate'
gem 'bullet'
@@ -91,6 +113,16 @@ group :development do
# used in swagger build
gem 'json_refs', git: 'https://github.com/tzmfreedom/json_refs', ref: 'e32deb0'
# When we want to squash migrations
gem 'squasher'
end
group :test do
# Cypress in rails.
gem 'cypress-on-rails', '~> 1.0'
# fast cleaning of database
gem 'database_cleaner'
end
group :development, :test do
@@ -114,4 +146,5 @@ group :development, :test do
gem 'simplecov', '0.17.1', require: false
gem 'spring'
gem 'spring-watcher-listen'
gem 'webmock'
end
+291 -196
View File
@@ -1,10 +1,3 @@
GIT
remote: https://github.com/chatwoot/twitty
revision: af4f3e45dca55e42c64f7741a1fedfaa94d36419
specs:
twitty (0.1.0)
oauth
GIT
remote: https://github.com/sds/mock_redis
revision: 16d00789f0341a3aac35126c0ffe97a596753ff9
@@ -25,168 +18,204 @@ GEM
specs:
action-cable-testing (0.6.1)
actioncable (>= 5.0)
actioncable (6.0.2.2)
actionpack (= 6.0.2.2)
actioncable (6.0.3.6)
actionpack (= 6.0.3.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.2.2)
actionpack (= 6.0.2.2)
activejob (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
actionmailbox (6.0.3.6)
actionpack (= 6.0.3.6)
activejob (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
mail (>= 2.7.1)
actionmailer (6.0.2.2)
actionpack (= 6.0.2.2)
actionview (= 6.0.2.2)
activejob (= 6.0.2.2)
actionmailer (6.0.3.6)
actionpack (= 6.0.3.6)
actionview (= 6.0.3.6)
activejob (= 6.0.3.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.2.2)
actionview (= 6.0.2.2)
activesupport (= 6.0.2.2)
actionpack (6.0.3.6)
actionview (= 6.0.3.6)
activesupport (= 6.0.3.6)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.2.2)
actionpack (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
actiontext (6.0.3.6)
actionpack (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
nokogiri (>= 1.8.5)
actionview (6.0.2.2)
activesupport (= 6.0.2.2)
actionview (6.0.3.6)
activesupport (= 6.0.3.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.2.2)
activesupport (= 6.0.2.2)
activejob (6.0.3.6)
activesupport (= 6.0.3.6)
globalid (>= 0.3.6)
activemodel (6.0.2.2)
activesupport (= 6.0.2.2)
activerecord (6.0.2.2)
activemodel (= 6.0.2.2)
activesupport (= 6.0.2.2)
activestorage (6.0.2.2)
actionpack (= 6.0.2.2)
activejob (= 6.0.2.2)
activerecord (= 6.0.2.2)
marcel (~> 0.3.1)
activesupport (6.0.2.2)
activemodel (6.0.3.6)
activesupport (= 6.0.3.6)
activerecord (6.0.3.6)
activemodel (= 6.0.3.6)
activesupport (= 6.0.3.6)
activerecord-import (1.0.7)
activerecord (>= 3.2)
activestorage (6.0.3.6)
actionpack (= 6.0.3.6)
activejob (= 6.0.3.6)
activerecord (= 6.0.3.6)
marcel (~> 1.0.0)
activesupport (6.0.3.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2)
zeitwerk (~> 2.2, >= 2.2.2)
acts-as-taggable-on (6.5.0)
activerecord (>= 5.0, < 6.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
administrate (0.14.0)
actionpack (>= 4.2)
actionview (>= 4.2)
activerecord (>= 4.2)
autoprefixer-rails (>= 6.0)
datetime_picker_rails (~> 0.0.7)
jquery-rails (>= 4.0)
kaminari (>= 1.0)
momentjs-rails (~> 2.8)
sassc-rails (~> 2.1)
selectize-rails (~> 0.6)
annotate (3.1.1)
activerecord (>= 3.2, < 7.0)
rake (>= 10.4, < 14.0)
ast (2.4.0)
attr_extras (6.2.3)
ast (2.4.1)
attr_extras (6.2.4)
autoprefixer-rails (9.8.6.3)
execjs
aws-eventstream (1.1.0)
aws-partitions (1.296.0)
aws-sdk-core (3.94.0)
aws-partitions (1.360.0)
aws-sdk-core (3.105.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.30.0)
aws-sdk-core (~> 3, >= 3.71.0)
aws-sdk-kms (1.37.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.61.2)
aws-sdk-core (~> 3, >= 3.83.0)
aws-sdk-s3 (1.79.1)
aws-sdk-core (~> 3, >= 3.104.3)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.1.1)
aws-eventstream (~> 1.0, >= 1.0.2)
aws-sigv4 (1.2.2)
aws-eventstream (~> 1, >= 1.0.2)
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
azure-storage-blob (2.0.0)
azure-storage-blob (2.0.1)
azure-storage-common (~> 2.0)
nokogiri (~> 1.10.4)
azure-storage-common (2.0.1)
nokogiri (~> 1.11.0.rc2)
azure-storage-common (2.0.2)
faraday (~> 1.0)
faraday_middleware (~> 1.0.0.rc1)
nokogiri (~> 1.10.4)
bcrypt (3.1.13)
net-http-persistent (~> 4.0)
nokogiri (~> 1.11.0.rc2)
barnes (0.0.8)
multi_json (~> 1)
statsd-ruby (~> 1.1)
bcrypt (3.1.15)
bindex (0.8.1)
bootsnap (1.4.6)
bootsnap (1.4.8)
msgpack (~> 1.0)
brakeman (4.8.1)
browser (4.0.0)
brakeman (4.9.0)
browser (5.3.1)
builder (3.2.4)
bullet (6.1.0)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
bundle-audit (0.1.0)
bundler-audit
bundler-audit (0.6.1)
bundler-audit (0.7.0.1)
bundler (>= 1.2.0, < 3)
thor (~> 0.18)
byebug (11.1.1)
chargebee (2.7.5)
json_pure (~> 2.1)
rest-client (>= 1.8, < 3.0)
coderay (1.1.2)
thor (>= 0.18, < 2)
byebug (11.1.3)
coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.1.6)
connection_pool (2.2.2)
commonmarker (0.21.1)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.8)
connection_pool (2.2.3)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crass (1.0.6)
declarative (0.0.10)
cypress-on-rails (1.8.0)
rack
database_cleaner (1.8.5)
datetime_picker_rails (0.0.7)
momentjs-rails (>= 2.8.1)
declarative (0.0.20)
declarative-option (0.1.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (4.7.1)
devise (4.7.2)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise_token_auth (1.1.3)
devise_token_auth (1.1.4)
bcrypt (~> 3.0)
devise (> 3.5.2, < 5)
rails (>= 4.2.0, < 6.1)
diff-lcs (1.3)
digest-crc (0.5.1)
sprockets (= 3.7.2)
diff-lcs (1.4.4)
digest-crc (0.6.1)
rake (~> 13.0)
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.5)
dotenv-rails (2.7.5)
dotenv (= 2.7.5)
railties (>= 3.2, < 6.1)
dotenv (2.7.6)
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
equalizer (0.0.11)
erubi (1.9.0)
erubi (1.10.0)
et-orbi (1.2.4)
tzinfo
execjs (2.7.0)
facebook-messenger (1.4.1)
facebook-messenger (1.5.0)
httparty (~> 0.13, >= 0.13.7)
rack (>= 1.4.5)
factory_bot (5.1.2)
activesupport (>= 4.2.0)
factory_bot_rails (5.1.1)
factory_bot (~> 5.1.0)
railties (>= 4.2.0)
faker (2.11.0)
factory_bot (6.1.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.1.0)
factory_bot (~> 6.1.0)
railties (>= 5.0.0)
faker (2.13.0)
i18n (>= 1.6, < 2)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
faraday_middleware (1.0.0)
faraday (~> 1.0)
ffi (1.12.2)
fcm (1.0.2)
faraday (~> 1.0.0)
ffi (1.14.2)
flag_shih_tzu (0.3.23)
foreman (0.87.1)
foreman (0.87.2)
fugit (1.4.1)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.4)
geocoder (1.6.3)
gli (2.19.2)
globalid (0.4.2)
activesupport (>= 4.2.0)
google-api-client (0.38.0)
google-api-client (0.43.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
@@ -197,59 +226,66 @@ GEM
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.3.1)
google-cloud-env (1.3.3)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.0)
google-cloud-storage (1.26.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.28.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.12.0)
googleauth (0.13.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
groupdate (5.0.0)
groupdate (5.1.0)
activesupport (>= 5)
haikunator (1.1.0)
hana (1.3.5)
hairtrigger (0.2.23)
activerecord (>= 5.0, < 7)
ruby2ruby (~> 2.4)
ruby_parser (~> 3.10)
hana (1.3.6)
hashdiff (1.0.1)
hashie (4.1.0)
hkdf (0.3.0)
http-accept (1.7.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
httparty (0.18.0)
httparty (0.18.1)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
i18n (1.8.2)
i18n (1.8.9)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
inflecto (0.0.2)
jaro_winkler (1.5.4)
jbuilder (2.10.0)
activesupport (>= 5.0.0)
jmespath (1.4.0)
json (2.3.0)
json_pure (2.3.0)
jwt (2.2.1)
kaminari (1.2.0)
jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.3.1)
jwt (2.2.2)
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.0)
kaminari-activerecord (= 1.2.0)
kaminari-core (= 1.2.0)
kaminari-actionview (1.2.0)
kaminari-actionview (= 1.2.1)
kaminari-activerecord (= 1.2.1)
kaminari-core (= 1.2.1)
kaminari-actionview (1.2.1)
actionview
kaminari-core (= 1.2.0)
kaminari-activerecord (1.2.0)
kaminari-core (= 1.2.1)
kaminari-activerecord (1.2.1)
activerecord
kaminari-core (= 1.2.0)
kaminari-core (1.2.0)
kaminari-core (= 1.2.1)
kaminari-core (1.2.1)
koala (3.0.0)
addressable
faraday
@@ -258,106 +294,112 @@ GEM
addressable (~> 2.7)
letter_opener (1.7.0)
launchy (~> 2.2)
listen (3.2.1)
liquid (4.0.3)
listen (3.3.3)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.5.0)
loofah (2.9.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
marcel (1.0.0)
maxminddb (0.1.22)
memoist (0.16.2)
method_source (1.0.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.1009)
mimemagic (0.3.4)
mime-types-data (3.2020.0512)
mini_magick (4.10.1)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.14.0)
mini_mime (1.0.3)
mini_portile2 (2.5.0)
minitest (5.14.4)
momentjs-rails (2.20.1)
railties (>= 3.1)
msgpack (1.3.3)
multi_json (1.14.1)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
net-http-persistent (4.0.0)
connection_pool (~> 2.2)
netrc (0.11.0)
nio4r (2.5.2)
nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
nio4r (2.5.7)
nokogiri (1.11.2)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
oauth (0.5.4)
orm_adapter (0.5.0)
os (1.1.0)
parallel (1.19.1)
parser (2.7.1.1)
ast (~> 2.4.0)
os (1.1.1)
parallel (1.19.2)
parser (2.7.1.4)
ast (~> 2.4.1)
pg (1.2.3)
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.4)
puma (4.3.3)
public_suffix (4.0.5)
puma (4.3.6)
nio4r (~> 2.0)
pundit (2.1.0)
activesupport (>= 3.0.0)
rack (2.2.2)
rack-cache (1.11.1)
raabro (1.4.0)
racc (1.5.2)
rack (2.2.3)
rack-cache (1.12.0)
rack (>= 0.4)
rack-cors (1.1.1)
rack (>= 2.0.0)
rack-protection (2.0.8.1)
rack
rack-proxy (0.6.5)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.2.2)
actioncable (= 6.0.2.2)
actionmailbox (= 6.0.2.2)
actionmailer (= 6.0.2.2)
actionpack (= 6.0.2.2)
actiontext (= 6.0.2.2)
actionview (= 6.0.2.2)
activejob (= 6.0.2.2)
activemodel (= 6.0.2.2)
activerecord (= 6.0.2.2)
activestorage (= 6.0.2.2)
activesupport (= 6.0.2.2)
rails (6.0.3.6)
actioncable (= 6.0.3.6)
actionmailbox (= 6.0.3.6)
actionmailer (= 6.0.3.6)
actionpack (= 6.0.3.6)
actiontext (= 6.0.3.6)
actionview (= 6.0.3.6)
activejob (= 6.0.3.6)
activemodel (= 6.0.3.6)
activerecord (= 6.0.3.6)
activestorage (= 6.0.3.6)
activesupport (= 6.0.3.6)
bundler (>= 1.3.0)
railties (= 6.0.2.2)
railties (= 6.0.3.6)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.2.2)
actionpack (= 6.0.2.2)
activesupport (= 6.0.2.2)
railties (6.0.3.6)
actionpack (= 6.0.3.6)
activesupport (= 6.0.3.6)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
rake (13.0.1)
rb-fsevent (0.10.3)
rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
redis (4.1.3)
redis-namespace (1.7.0)
redis (4.2.1)
redis-namespace (1.8.0)
redis (>= 3.0.4)
redis-rack-cache (2.2.1)
rack-cache (>= 1.10, < 2)
redis-store (>= 1.6, < 2)
redis-store (1.8.2)
redis-store (1.9.0)
redis (>= 4, < 5)
regexp_parser (1.7.1)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
responders (3.0.0)
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
rest-client (2.1.0)
@@ -367,15 +409,15 @@ GEM
netrc (~> 0.8)
retriable (3.1.2)
rexml (3.2.4)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.1)
rspec-core (3.9.2)
rspec-support (~> 3.9.3)
rspec-expectations (3.9.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-rails (4.0.0)
rspec-rails (4.0.1)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
@@ -383,46 +425,70 @@ GEM
rspec-expectations (~> 3.9)
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-support (3.9.2)
rubocop (0.81.0)
jaro_winkler (~> 1.5.1)
rspec-support (3.9.3)
rubocop (0.89.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
rubocop-rails (2.5.2)
activesupport
rubocop-ast (0.3.0)
parser (>= 2.7.1.4)
rubocop-performance (1.7.1)
rubocop (>= 0.82.0)
rubocop-rails (2.8.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rspec (1.38.1)
rubocop (>= 0.68.1)
rubocop (>= 0.87.0)
rubocop-rspec (1.43.2)
rubocop (~> 0.87)
ruby-enum (0.9.0)
i18n
ruby-progressbar (1.10.1)
ruby2ruby (2.4.4)
ruby_parser (~> 3.1)
sexp_processor (~> 4.6)
ruby_parser (3.15.0)
rubocop (>= 0.87.0)
sexp_processor (~> 4.9)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
scout_apm (2.6.7)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
scout_apm (2.6.9)
parser
scss_lint (0.59.0)
sass (~> 3.5, >= 3.5.5)
seed_dump (3.3.1)
activerecord (>= 4)
activesupport (>= 4)
selectize-rails (0.12.6)
semantic_range (2.3.0)
sentry-raven (3.0.0)
sentry-raven (3.0.3)
faraday (>= 1.0)
shoulda-matchers (4.3.0)
sexp_processor (4.15.1)
shoulda-matchers (4.4.1)
activesupport (>= 4.2.0)
sidekiq (6.0.6)
sidekiq (6.1.1)
connection_pool (>= 2.2.2)
rack (~> 2.0)
rack-protection (>= 2.0.0)
redis (>= 4.1.0)
redis (>= 4.2.0)
sidekiq-cron (1.2.0)
fugit (~> 1.1)
sidekiq (>= 4.2.1)
signet (0.14.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
@@ -433,24 +499,33 @@ GEM
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
spring (2.1.0)
slack-ruby-client (0.15.0)
faraday (>= 1.0)
faraday_middleware
gli
hashie
websocket-driver
spring (2.1.1)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
sprockets (4.0.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
sprockets-rails (3.2.2)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
squasher (0.6.2)
statsd-ruby (1.4.0)
telegram-bot-ruby (0.12.0)
faraday
inflecto
virtus
telephone_number (1.4.6)
thor (0.20.3)
telephone_number (1.4.9)
thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
time_diff (0.3.0)
activesupport
i18n
@@ -458,9 +533,11 @@ GEM
faraday (~> 1.0.0)
jwt (>= 1.5, <= 2.5)
nokogiri (>= 1.6, < 2.0)
tzinfo (1.2.7)
twitty (0.1.1)
oauth
tzinfo (1.2.9)
thread_safe (~> 0.1)
tzinfo-data (1.2019.3)
tzinfo-data (1.2020.1)
tzinfo (>= 1.0.0)
uber (0.1.0)
uglifier (4.2.0)
@@ -470,7 +547,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
uniform_notifier (1.13.0)
valid_email2 (3.2.2)
valid_email2 (3.3.1)
activemodel (>= 3.2)
mail (~> 2.5)
virtus (1.0.5)
@@ -480,12 +557,16 @@ GEM
equalizer (~> 0.0, >= 0.0.9)
warden (1.2.8)
rack (>= 2.0.6)
web-console (4.0.1)
web-console (4.0.4)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webpacker (5.0.1)
webmock (3.8.3)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.2.1)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
@@ -493,40 +574,48 @@ GEM
webpush (1.0.0)
hkdf (~> 0.2)
jwt (~> 2.0)
websocket-driver (0.7.1)
websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
websocket-extensions (0.1.5)
wisper (2.0.0)
zeitwerk (2.3.0)
zeitwerk (2.4.2)
PLATFORMS
ruby
DEPENDENCIES
action-cable-testing
activerecord-import
acts-as-taggable-on
administrate
annotate
attr_extras
aws-sdk-s3
azure-storage-blob
barnes
bootsnap
brakeman
browser
bullet
bundle-audit
byebug
chargebee
commonmarker
cypress-on-rails (~> 1.0)
database_cleaner
devise
devise_token_auth
dotenv-rails
facebook-messenger
facebook-messenger (= 1.5.0)
factory_bot_rails
faker
fcm
flag_shih_tzu
foreman
geocoder
google-cloud-storage
groupdate
haikunator
hairtrigger
hashie
jbuilder
json_refs!
@@ -534,7 +623,9 @@ DEPENDENCIES
kaminari
koala
letter_opener
liquid
listen
maxminddb
mini_magick
mock_redis!
pg
@@ -559,24 +650,28 @@ DEPENDENCIES
sentry-raven
shoulda-matchers
sidekiq
sidekiq-cron
simplecov (= 0.17.1)
slack-ruby-client
spring
spring-watcher-listen
squasher
telegram-bot-ruby
telephone_number
time_diff
twilio-ruby (~> 5.32.0)
twitty!
twitty
tzinfo-data
uglifier
valid_email2
web-console
webpacker
webmock
webpacker (~> 5.x)
webpush
wisper (= 2.0.0)
RUBY VERSION
ruby 2.7.0p0
ruby 2.7.2p137
BUNDLED WITH
2.1.2
2.1.4
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2017-2020 ThoughtWoot Inc.
Copyright (c) 2017-2021 Chatwoot Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+2 -1
View File
@@ -1,2 +1,3 @@
release: bundle exec rails db:chatwoot_prepare
web: bin/rails server -p $PORT -e $RAILS_ENV
worker: bundle exec sidekiq -C config/sidekiq.yml
worker: bundle exec sidekiq -C config/sidekiq.yml
+3
View File
@@ -0,0 +1,3 @@
backend: RAILS_ENV=test bin/rails s -p 5050
frontend: bin/webpack-dev-server
worker: RAILS_ENV=test bundle exec sidekiq -C config/sidekiq.yml
+55 -20
View File
@@ -19,48 +19,83 @@ ___
<a href="https://hub.docker.com/r/chatwoot/chatwoot/"><img src="https://img.shields.io/docker/cloud/build/chatwoot/chatwoot" alt="Docker Build Badge"></a>
<img src="https://img.shields.io/github/license/chatwoot/chatwoot" alt="License">
<img src="https://img.shields.io/github/commit-activity/m/chatwoot/chatwoot" alt="Commits-per-month">
<img src="https://img.shields.io/discord/647412545203994635" alt="Discord">
<a href="https://discord.gg/cJXdrwS"><img src="https://img.shields.io/badge/chat-Discord-violet?logo=discord" alt="Chat on Discord"></a>
<a title="Crowdin" target="_self" href="https://chatwoot.crowdin.com/chatwoot"><img src="https://badges.crowdin.net/e/37ced7eba411064bd792feb3b7a28b16/localized.svg"></a>
<a href="https://discord.gg/cJXdrwS"><img src="https://img.shields.io/discord/647412545203994635" alt="Discord"></a>
</p>
![ChatUI progess](https://s3.us-west-2.amazonaws.com/gh-assets.chatwoot.com/chatwoot-dashboard-assets.png)
<img src="https://s3.us-west-2.amazonaws.com/gh-assets.chatwoot.com/chatwoot-dashboard-assets.png" width="100%" alt="Chat dashboard"/>
## Background
Chatwoot is an open-source omnichannel customer support software. The development of Chatwoot started in 2016. It failed to succeed as a business and eventually shut up shop in 2017. During 2019 #Hacktoberfest, the maintainers decided to make it open-source, instead of letting the code rust in a private repo. With a pleasant surprise, Chatwoot became a trending project on Hacker News and best of all, got lots of love from the community.
Now, a failed project is back on track and the prospects are looking great. The team is back to working on the project and this time, we are building it in the open. Thanks to the ideas and contributions from the community.
Chatwoot is a customer support tool for instant messaging channels which can help businesses to provide exceptional customer support. The development of Chatwoot started in 2016 and it failed to succeed as a business and eventually shut the shop in 2017. During 2019 #Hacktoberfest, the maintainers decided to make it opensource instead of letting the code rust in a private repo. With a pleasant surprise, Chatwoot became a trending project on Hacker News and best of all, got lots of love from the community.
---
Now, a failed project is back on track and the prospects are looking great. The team is back to working on the project and we are building it in the open. Thanks to the ideas and contributions from the community.
### Features
## Documentation
Chatwoot gives an integrated view of conversations happening in different communication channels.
Detailed documentation is available at [www.chatwoot.com/docs](https://www.chatwoot.com/docs).
It supports the following conversation channels:
You can find the quick setup docs [here](https://www.chatwoot.com/docs/quick-setup).
- **Website**: Talk to your customers using our live chat widget and make use of our SDK to identify a user and provide contextual support.
- **Facebook**: Connect your Facebook pages and start replying to the direct messages to your page.
- **Twitter**: Connect your Twitter profiles and reply to direct messages or the tweets where you are mentioned.
- **Whatsapp**: Connect your Whatsapp business account and manage the conversation in Chatwoot
- **SMS**: Connect your Twilio SMS account and reply to the SMS queries in Chatwoot
- **API Channel**: Build custom communication channels using our API channel.
- **Email (beta)**: Forward all your email queries to Chatwoot and view it in our integrated dashboard.
## Branching model
Other features include:
We use [git-flow](https://nvie.com/posts/a-successful-git-branching-model/) branching model. The base branch is `develop`.
If you are looking for a stable version, please use the `master` or tags labelled as `v1.x.x`.
- **Multi-brand inboxes**: Manage multiple brands or pages using a single dashboard.
- **Private notes**: Inter team communication is possible using private notes in a conversation.
- **Canned responses (Saved replies)**: Improve the response rate by adding saved replies for frequently asked questions.
- **Conversation Labels**: Use conversation labelling to create custom workflows.
- **Auto assignment**: Chatwoot intelligently assigns a ticket to the agents who have access to the inbox depending on their availability and load.
- **Conversation continuity**: If the user has provided an email address through the chat widget, Chatwoot would send an email to the customer under the agent name so that the user can continue the conversation over the email.
- **Multi-lingual support**: Chatwoot supports 10+ languages.
- **Powerful API & Webhooks**: Extend the capability of the software using Chatwoots webhooks and APIs.
- **Integrations**: Chatwoot natively integrates with Slack right now. Manage your conversations in Slack without logging into the dashboard.
## Heroku one-click deploy
---
Deploying chatwoot to heroku, it's a breeze. It's as simple as clicking this button.
### Documentation
Detailed documentation is available at [www.chatwoot.com/help-center](https://www.chatwoot.com/help-center).
### Translation process
The translation process for Chatwoot web and mobile app is managed at [https://translate.chatwoot.com](https://translate.chatwoot.com) using Crowdin. Please read the [translation guide](https://www.chatwoot.com/docs/contributing/translating-chatwoot-to-your-language) for contributing to Chatwoot.
---
### Branching model
We use the [git-flow](https://nvie.com/posts/a-successful-git-branching-model/) branching model. The base branch is `develop`.
If you are looking for a stable version, please use the `master` or tags labelled as `v1.x.x`.
---
### Deployment
#### Heroku one-click deploy
Deploying Chatwoot to Heroku is a breeze. It's as simple as clicking this button:
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/chatwoot/chatwoot/tree/master)
Follow this [link](https://www.chatwoot.com/docs/environment-variables) to understand setting the correct environment variables for the app to work with all the features. There might be breakages if you do not set the relevant environment variables. This applies to deploying the docker image as well.
Follow this [link](https://www.chatwoot.com/docs/environment-variables) to understand setting the correct environment variables for the app to work with all the features. There might be breakages if you do not set the relevant environment variables.
## Docker
#### Other deployment options
Follow our [docker development guide](https://www.chatwoot.com/docs/installation-guide-docker) to develop and debug the application using `docker-compose`.
Please follow [deployment architecture guide](https://www.chatwoot.com/docs/deployment/architecture) to deploy with Docker or Caprover.
Follow our [environment variables](https://www.chatwoot.com/docs/environment-variables/) guide to setup environment for Docker.
---
## Contributors ✨
### Contributors ✨
Thanks goes to all these [wonderful people](https://www.chatwoot.com/docs/contributors):
<a href="https://github.com/chatwoot/chatwoot/graphs/contributors"><img src="https://opencollective.com/chatwoot/contributors.svg?width=890&button=false" /></a>
*Chatwoot* &copy; 2017-2020, ThoughtWoot Inc - Released under the MIT License.
*Chatwoot* &copy; 2017-2021, Chatwoot Inc - Released under the MIT License.
+11 -16
View File
File diff suppressed because one or more lines are too long
+4 -1
View File
@@ -33,7 +33,10 @@ class ContactIdentifyAction
end
def update_contact
@contact.update!(params.slice(:name, :email, :identifier))
custom_attributes = params[:custom_attributes] ? @contact.custom_attributes.merge(params[:custom_attributes]) : @contact.custom_attributes
# blank identifier or email will throw unique index error
# TODO: replace reject { |_k, v| v.blank? } with compact_blank when rails is upgraded
@contact.update!(params.slice(:name, :email, :identifier).reject { |_k, v| v.blank? }.merge({ custom_attributes: custom_attributes }))
ContactAvatarJob.perform_later(@contact, params[:avatar_url]) if params[:avatar_url].present?
end
+1 -1
View File
@@ -29,7 +29,7 @@ class ContactMergeAction
end
def merge_messages
Message.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
Message.where(sender: @mergee_contact).update(sender: @base_contact)
end
def merge_contact_inboxes
+3
View File
@@ -1 +1,4 @@
//= link_tree ../images
//= link administrate/application.css
//= link administrate/application.js
//= link dashboardChart.js
+55
View File
@@ -0,0 +1,55 @@
// eslint-disable-next-line
function prepareData(data) {
var labels = [];
var dataSet = [];
data.forEach(item => {
labels.push(item[0]);
dataSet.push(item[1]);
});
return { labels, dataSet };
}
function getChartOptions() {
var fontFamily =
'Inter,-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
return {
responsive: true,
legend: { labels: { fontFamily } },
scales: {
xAxes: [
{
barPercentage: 1.26,
ticks: { fontFamily },
gridLines: { display: false },
},
],
yAxes: [
{
ticks: { fontFamily },
gridLines: { display: false },
},
],
},
};
}
// eslint-disable-next-line
function drawSuperAdminDashboard(data) {
var ctx = document.getElementById('dashboard-chart').getContext('2d');
var chartData = prepareData(data);
// eslint-disable-next-line
new Chart(ctx, {
type: 'bar',
data: {
labels: chartData.labels,
datasets: [
{
label: 'Conversations',
data: chartData.dataSet,
backgroundColor: '#1f93ff',
},
],
},
options: getChartOptions(),
});
}
@@ -0,0 +1,32 @@
@charset 'utf-8';
@import 'reset/normalize';
@import 'utilities/variables';
@import 'utilities/text-color';
@import 'selectize';
@import 'datetime_picker';
@import 'library/clearfix';
@import 'library/data-label';
@import 'library/variables';
@import 'base/forms';
@import 'base/layout';
@import 'base/lists';
@import 'base/tables';
@import 'base/typography';
@import 'components/app-container';
@import 'components/attributes';
@import 'components/buttons';
@import 'components/cells';
@import 'components/field-unit';
@import 'components/flashes';
@import 'components/form-actions';
@import 'components/main-content';
@import 'components/navigation';
@import 'components/pagination';
@import 'components/search';
@import 'components/reports';
@@ -0,0 +1,103 @@
fieldset {
background-color: transparent;
border: 0;
margin: 0;
padding: 0;
}
legend {
font-weight: $font-weight-medium;
margin: 0;
padding: 0;
}
label {
display: block;
font-weight: $font-weight-medium;
margin: 0;
}
input,
select {
display: block;
font-family: $base-font-family;
font-size: $base-font-size;
}
input,
select,
textarea {
display: block;
font-family: $base-font-family;
font-size: 16px;
}
[type="color"],
[type="date"],
[type="datetime-local"],
[type="email"],
[type="month"],
[type="number"],
[type="password"],
[type="search"],
[type="tel"],
[type="text"],
[type="time"],
[type="url"],
[type="week"],
input:not([type]),
textarea {
appearance: none;
background-color: $white;
border: $base-border;
border-radius: $base-border-radius;
padding: 0.5em;
transition: border-color $base-duration $base-timing;
width: 100%;
&:hover {
border-color: mix($black, $base-border-color, 20%);
}
&:focus {
border-color: $action-color;
outline: none;
}
&:disabled {
background-color: mix($black, $white, 5%);
cursor: not-allowed;
&:hover {
border: $base-border;
}
}
}
textarea {
resize: vertical;
}
[type="checkbox"],
[type="radio"] {
display: inline;
margin-right: $small-spacing / 2;
}
[type="file"] {
width: 100%;
}
select {
width: 100%;
}
[type="checkbox"],
[type="radio"],
[type="file"],
select {
&:focus {
outline: $focus-outline;
outline-offset: $focus-outline-offset;
}
}
@@ -0,0 +1,22 @@
html {
background-color: $color-white;
box-sizing: border-box;
font-size: 10px;
-webkit-font-smoothing: antialiased;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
figure {
margin: 0;
}
img,
picture {
margin: 0;
max-width: 100%;
}
@@ -0,0 +1,19 @@
ul,
ol {
list-style-type: none;
margin: 0;
padding: 0;
}
dl {
margin-bottom: $small-spacing;
dt {
font-weight: $font-weight-medium;
margin-top: $small-spacing;
}
dd {
margin: 0;
}
}
@@ -0,0 +1,71 @@
table {
border-collapse: collapse;
font-size: $font-size-default;
text-align: left;
width: 100%;
a {
color: inherit;
text-decoration: none;
}
}
tr {
border-bottom: $base-border;
th {
font-weight: $font-weight-medium;
&.cell-label--avatar-field {
a {
display: none;
}
}
}
}
tbody tr {
&:hover {
background-color: $base-background-color;
cursor: pointer;
}
&:focus {
outline: $focus-outline;
outline-offset: -($focus-outline-width);
}
td {
&.cell-data--avatar-field {
line-height: 1;
text-align: center;
img {
border-radius: 50%;
height: $space-large;
max-height: $space-large;
width: $space-large;
}
}
}
}
td,
th {
padding: $space-slab;
vertical-align: middle;
}
td:first-child,
th:first-child {
padding-left: 0;
}
td:last-child,
th:last-child {
padding-right: 0;
}
td img {
max-height: 2rem;
}
@@ -0,0 +1,44 @@
body {
color: $base-font-color;
font-family: $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: $heading-font-family;
font-size: $base-font-size;
line-height: $heading-line-height;
margin: 0;
}
p {
margin: 0 0 $small-spacing;
}
a {
color: $action-color;
transition: color $base-duration $base-timing;
&:hover {
color: mix($black, $action-color, 25%);
}
&:focus {
outline: $focus-outline;
outline-offset: $focus-outline-offset;
}
}
hr {
border-bottom: $base-border;
border-left: 0;
border-right: 0;
border-top: 0;
margin: $base-spacing 0;
}
@@ -0,0 +1,8 @@
.app-container {
align-items: stretch;
display: flex;
margin-left: auto;
margin-right: auto;
max-width: 100rem;
min-height: 100vh;
}
@@ -0,0 +1,26 @@
.attribute-label {
@include data-label;
clear: left;
float: left;
margin-bottom: $base-spacing;
margin-top: 0.25em;
text-align: right;
width: calc(15% - 1rem);
}
.preserve-whitespace {
white-space: pre-wrap;
word-wrap: break-word;
}
.attribute-data {
float: left;
margin-bottom: $base-spacing;
margin-left: 2rem;
width: calc(85% - 1rem);
}
.attribute--nested {
border: $base-border;
padding: $small-spacing;
}
@@ -0,0 +1,50 @@
button,
input[type="button"],
input[type="reset"],
input[type="submit"],
.button {
appearance: none;
background-color: $color-woot;
border: 0;
border-radius: $base-border-radius;
color: $white;
cursor: pointer;
display: inline-block;
font-size: $font-size-default;
-webkit-font-smoothing: antialiased;
font-weight: $font-weight-medium;
line-height: 1;
padding: $space-one $space-two;
text-decoration: none;
transition: background-color $base-duration $base-timing;
user-select: none;
vertical-align: middle;
white-space: nowrap;
&:hover {
background-color: mix($black, $color-woot, 20%);
color: $white;
}
&:focus {
outline: $focus-outline;
outline-offset: $focus-outline-offset;
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
&:hover {
background-color: $color-woot;
}
}
}
.button--alt {
background-color: transparent;
border: $base-border;
border-color: $blue;
color: $blue;
margin-bottom: $base-spacing;
}
@@ -0,0 +1,45 @@
.cell-label {
&:hover {
a {
color: $action-color;
}
svg {
fill: $action-color;
transform: rotate(180deg);
}
}
a {
color: inherit;
display: inline-block;
transition: color $base-duration $base-timing;
width: 100%;
}
}
.cell-label--asc,
.cell-label--desc {
font-weight: $font-weight-medium;
}
.cell-label__sort-indicator {
float: right;
margin-left: 5px;
svg {
fill: $hint-grey;
height: 13px;
transition: transform $base-duration $base-timing;
width: 13px;
}
}
.cell-label__sort-indicator--desc {
transform: rotate(180deg);
}
.cell-data--number,
.cell-label--number {
text-align: right;
}
@@ -0,0 +1,54 @@
.field-unit {
@include administrate-clearfix;
align-items: center;
display: flex;
margin-bottom: $base-spacing;
position: relative;
width: 100%;
}
.field-unit__label {
float: left;
margin-left: 1rem;
text-align: right;
width: calc(15% - 1rem);
}
.field-unit__field {
float: left;
margin-left: 2rem;
max-width: 50rem;
width: 100%;
}
.field-unit--nested {
border: $base-border;
margin-left: 7.5%;
max-width: 60rem;
padding: $small-spacing;
width: 100%;
.field-unit__field {
width: 100%;
}
.field-unit__label {
width: 10rem;
}
}
.field-unit--required {
label::after {
color: $red;
content: ' *';
}
}
.attribute-data--avatar-field {
height: $space-larger;
width: $space-larger;
img {
border-radius: 50%;
}
}
@@ -0,0 +1,28 @@
$base-spacing: 1.5em !default;
$flashes: (
"alert": #fff6bf,
"error": #fbe3e4,
"notice": #e5edf8,
"success": #e6efc2,
) !default;
@each $flash-type, $color in $flashes {
.flash-#{$flash-type} {
background-color: $color;
color: mix($black, $color, 60%);
display: block;
margin-bottom: $base-spacing / 2;
padding: $base-spacing / 2;
text-align: center;
a {
color: mix($black, $color, 70%);
text-decoration: underline;
&:focus,
&:hover {
color: mix($black, $color, 90%);
}
}
}
}
@@ -0,0 +1,3 @@
.form-actions {
margin-left: calc(15% + 2rem);
}
@@ -0,0 +1,26 @@
.main-content {
font-size: $font-size-default;
left: 23rem;
position: absolute;
right: 0;
top: 0;
}
.main-content__body {
padding: $space-two;
}
.main-content__header {
align-items: center;
background-color: $color-white;
border-bottom: 1px solid $color-border;
display: flex;
min-height: 5.6rem;
padding: $space-small $space-normal;
}
.main-content__page-title {
font-size: $font-size-large;
font-weight: $font-weight-medium;
margin-right: auto;
}
@@ -0,0 +1,78 @@
.logo-brand {
margin-bottom: $space-normal;
padding: $space-normal $space-smaller $space-small;
text-align: center;
}
.navigation {
background: $white;
border-right: 1px solid $color-border;
display: flex;
flex-direction: column;
font-size: $font-size-default;
font-weight: $font-weight-medium;
height: 100%;
justify-content: flex-start;
left: 0;
margin: 0;
overflow: auto;
padding: $space-normal;
position: fixed;
top: 0;
width: 23rem;
z-index: 1023;
li {
align-items: center;
display: flex;
a {
color: $color-gray;
text-decoration: none;
}
i {
min-width: $space-medium;
}
}
}
.navigation__link {
background-color: transparent;
color: $color-gray;
display: block;
line-height: 1;
margin-bottom: $space-smaller;
padding: $space-one;
&:hover {
color: $blue;
a {
color: $blue;
}
}
&.navigation__link--active {
background-color: $color-background;
border-radius: $base-border-radius;
color: $blue;
a {
color: $blue;
}
}
}
.logout {
bottom: $space-normal;
left: $space-normal;
position: fixed;
}
.app-version {
color: $color-gray;
font-size: $font-size-small;
padding-top: $space-smaller;
}
@@ -0,0 +1,19 @@
.pagination {
font-size: $font-size-default;
margin-top: $base-spacing;
padding-left: $base-spacing;
padding-right: $base-spacing;
text-align: center;
.first,
.prev,
.page,
.next,
.last {
margin: $small-spacing;
}
.current {
font-weight: $font-weight-medium;
}
}
@@ -0,0 +1,15 @@
.report--list {
display: flex;
padding: 0 $space-two $space-larger;
}
.report-card {
flex: 1;
font-size: $font-size-small;
text-align: center;
.metric {
font-size: $font-size-bigger;
font-weight: 200;
}
}
@@ -0,0 +1,44 @@
.search {
margin-left: auto;
margin-right: 2rem;
max-width: 44rem;
position: relative;
width: 100%;
}
.search__input {
background: $grey-1;
padding-left: $space-normal * 2.5;
padding-right: $space-normal * 2.5;
}
.search__eyeglass-icon {
fill: $grey-7;
height: $space-normal;
left: $space-normal;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: $space-normal;
}
.search__clear-link {
height: $space-normal;
position: absolute;
right: $space-normal * 0.75;
top: 50%;
transform: translateY(-50%);
width: $space-normal;
}
.search__clear-icon {
fill: $grey-5;
height: $space-normal;
position: absolute;
transition: fill $base-duration $base-timing;
width: $space-normal;
&:hover {
fill: $action-color;
}
}
@@ -0,0 +1,7 @@
@mixin administrate-clearfix {
&::after {
clear: both;
content: '';
display: block;
}
}
@@ -0,0 +1,8 @@
@mixin data-label {
color: $hint-grey;
font-size: 0.8em;
font-weight: 400;
letter-spacing: 0.0357em;
position: relative;
text-transform: uppercase;
}
@@ -0,0 +1,61 @@
// Typography
$base-font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif !default;
$heading-font-family: $base-font-family !default;
$base-font-size: 10px !default;
$base-line-height: 1.5 !default;
$heading-line-height: 1.2 !default;
// Other Sizes
$base-border-radius: 4px !default;
$base-spacing: $base-line-height * 1em !default;
$small-spacing: $base-spacing / 2 !default;
// Colors
$white: #fff !default;
$black: #000 !default;
$blue: #1f93ff !default;
$red: #ff382d !default;
$light-yellow: #ffc532 !default;
$light-green: #44ce4b !default;
$grey-0: #f6f7f7 !default;
$grey-1: #f0f4f5 !default;
$grey-2: #cfd8dc !default;
$grey-5: #adb5bd !default;
$grey-7: #293f54 !default;
$hint-grey: #7b808c !default;
// Font Colors
$base-font-color: $grey-7 !default;
$action-color: $blue !default;
// Background Colors
$base-background-color: $grey-0 !default;
// Focus
$focus-outline-color: transparentize($action-color, 0.4);
$focus-outline-width: 3px;
$focus-outline: $focus-outline-width solid $focus-outline-color;
$focus-outline-offset: 1px;
// Flash Colors
$flash-colors: (
alert: $light-yellow,
error: $red,
notice: mix($white, $blue, 50%),
success: $light-green
);
// Border
$base-border-color: $grey-1 !default;
$base-border: 1px solid $base-border-color !default;
// Transitions
$base-duration: 250ms !default;
$base-timing: ease-in-out !default;
@@ -0,0 +1,448 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
-moz-osx-font-smoothing: grayscale;
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}
@@ -0,0 +1,3 @@
.text-color-red {
color: $alert-color;
}
@@ -0,0 +1,98 @@
// Font sizes
$font-size-nano: 0.8rem;
$font-size-micro: 1.0rem;
$font-size-mini: 1.2rem;
$font-size-small: 1.4rem;
$font-size-default: 1.6rem;
$font-size-medium: 1.8rem;
$font-size-large: 2.2rem;
$font-size-big: 2.4rem;
$font-size-bigger: 3.0rem;
$font-size-mega: 3.4rem;
$font-size-giga: 4.0rem;
// spaces
$zero: 0;
$space-micro: 0.2rem;
$space-smaller: 0.4rem;
$space-small: 0.8rem;
$space-one: 1rem;
$space-slab: 1.2rem;
$space-normal: 1.6rem;
$space-two: 2.0rem;
$space-medium: 2.4rem;
$space-large: 3.2rem;
$space-larger: 4.8rem;
$space-jumbo: 6.4rem;
$space-mega: 10.0rem;
// font-weight
$font-weight-feather: 100;
$font-weight-light: 300;
$font-weight-normal: 400;
$font-weight-medium: 500;
$font-weight-bold: 600;
$font-weight-black: 700;
//Navbar
$nav-bar-width: 23rem;
$header-height: 5.6rem;
$woot-logo-padding: $space-large $space-two;
// Colors
$color-woot: #1f93ff;
$color-gray: #6e6f73;
$color-light-gray: #999a9b;
$color-border: #e0e6ed;
$color-border-light: #f0f4f5;
$color-background: #f4f6fb;
$color-border-dark: #cad0d4;
$color-background-light: #f9fafc;
$color-white: #fff;
$color-body: #3c4858;
$color-heading: #1f2d3d;
$color-extra-light-blue: #f5f7f9;
$primary-color: $color-woot;
$secondary-color: #35c5ff;
$success-color: #44ce4b;
$warning-color: #ffc532;
$alert-color: #ff382d;
$masked-bg: rgba(0, 0, 0, .4);
// Color-palettes
$color-primary-light: #c7e3ff;
$color-primary-dark: darken($color-woot, 20%);
// Thumbnail
$thumbnail-radius: 4rem;
// chat-header
$conv-header-height: 4rem;
// Inbox List
$inbox-thumb-size: 4.8rem;
// Spinner
$spinkit-spinner-color: $color-white !default;
$spinkit-spinner-margin: 0 0 0 1.6rem !default;
$spinkit-size: 1.6rem !default;
// Snackbar default
$woot-snackbar-bg: #323232;
$woot-snackbar-button: #ffeb3b;
$swift-ease-out-duration: .4s !default;
$swift-ease-out-timing-function: cubic-bezier(.25, .8, .25, 1) !default;
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
// Ionicons
$ionicons-font-path: '~ionicons/fonts';
// Transitions
$transition-ease-in: all 0.250s ease-in;
-19
View File
@@ -1,19 +0,0 @@
# app/bot/facebook_bot.rb
require 'facebook/messenger'
include Facebook::Messenger
Bot.on :message do |message|
response = ::Integrations::Facebook::MessageParser.new(message)
::Integrations::Facebook::MessageCreator.new(response).perform
end
Bot.on :delivery do |delivery|
# delivery.ids # => 'mid.1457764197618:41d102a3e1ae206a38'
# delivery.sender # => { 'id' => '1008372609250235' }
# delivery.recipient # => { 'id' => '2015573629214912' }
# delivery.at # => 2016-04-22 21:30:36 +0200
# delivery.seq # => 37
updater = Integrations::Facebook::DeliveryStatus.new(delivery)
updater.perform
puts "Human was online at #{delivery.at}"
end
+28
View File
@@ -0,0 +1,28 @@
require 'facebook/messenger'
class FacebookBot
include Facebook::Messenger
Bot.on :message do |message|
Rails.logger.info "MESSAGE_RECIEVED #{message}"
response = ::Integrations::Facebook::MessageParser.new(message)
::Integrations::Facebook::MessageCreator.new(response).perform
end
Bot.on :delivery do |delivery|
# delivery.ids # => 'mid.1457764197618:41d102a3e1ae206a38'
# delivery.sender # => { 'id' => '1008372609250235' }
# delivery.recipient # => { 'id' => '2015573629214912' }
# delivery.at # => 2016-04-22 21:30:36 +0200
# delivery.seq # => 37
updater = Integrations::Facebook::DeliveryStatus.new(delivery)
updater.perform
Rails.logger.info "Human was online at #{delivery.at}"
end
Bot.on :message_echo do |message|
Rails.logger.info "MESSAGE_ECHO #{message}"
response = ::Integrations::Facebook::MessageParser.new(message)
::Integrations::Facebook::MessageCreator.new(response).perform
end
end
+19 -15
View File
@@ -2,17 +2,19 @@
class AccountBuilder
include CustomExceptions::Account
pattr_initialize [:account_name!, :email!]
pattr_initialize [:account_name!, :email!, :confirmed!, :user, :user_full_name, :user_password]
def perform
validate_email
validate_user
if @user.nil?
validate_email
validate_user
end
ActiveRecord::Base.transaction do
@account = create_account
@user = create_and_link_user
end
[@user, @account]
rescue StandardError => e
@account&.destroy
puts e.inspect
raise e
end
@@ -24,7 +26,7 @@ class AccountBuilder
if address.valid? # && !address.disposable?
true
else
raise InvalidEmail.new(valid: address.valid?) # , disposable: address.disposable?})
raise InvalidEmail.new(valid: address.valid?)
end
end
@@ -37,16 +39,12 @@ class AccountBuilder
end
def create_account
@account = Account.create!(name: @account_name)
@account = Account.create!(name: @account_name, locale: I18n.locale)
Current.account = @account
end
def create_and_link_user
password = Time.now.to_i
@user = User.new(email: @email,
password: password,
password_confirmation: password,
name: email_to_name(@email))
if @user.save!
if @user.present? || create_user
link_user_to_account(@user, @account)
@user
else
@@ -62,8 +60,14 @@ class AccountBuilder
)
end
def email_to_name(email)
name = email[/[^@]+/]
name.split('.').map(&:capitalize).join(' ')
def create_user
password = user_password || SecureRandom.alphanumeric(12)
@user = User.new(email: @email,
password: password,
password_confirmation: password,
name: @user_full_name)
@user.confirm if @confirmed
@user.save!
end
end
+38 -17
View File
@@ -5,7 +5,7 @@ class ContactBuilder
contact_inbox = inbox.contact_inboxes.find_by(source_id: source_id)
return contact_inbox if contact_inbox
build_contact
build_contact_inbox
end
private
@@ -14,25 +14,46 @@ class ContactBuilder
@account ||= inbox.account
end
def build_contact
ActiveRecord::Base.transaction do
contact = account.contacts.create!(
name: contact_attributes[:name],
phone_number: contact_attributes[:phone_number],
email: contact_attributes[:email],
identifier: contact_attributes[:identifier],
additional_attributes: contact_attributes[:additional_attributes]
)
contact_inbox = ::ContactInbox.create!(
contact_id: contact.id,
inbox_id: inbox.id,
source_id: source_id
)
def create_contact_inbox(contact)
::ContactInbox.create!(
contact_id: contact.id,
inbox_id: inbox.id,
source_id: source_id
)
end
::ContactAvatarJob.perform_later(contact, contact_attributes[:avatar_url]) if contact_attributes[:avatar_url]
def update_contact_avatar(contact)
::ContactAvatarJob.perform_later(contact, contact_attributes[:avatar_url]) if contact_attributes[:avatar_url]
end
def create_contact
account.contacts.create!(
name: contact_attributes[:name],
phone_number: contact_attributes[:phone_number],
email: contact_attributes[:email],
identifier: contact_attributes[:identifier],
additional_attributes: contact_attributes[:additional_attributes]
)
end
def find_contact
contact = nil
contact = account.contacts.find_by(identifier: contact_attributes[:identifier]) if contact_attributes[:identifier].present?
contact ||= account.contacts.find_by(email: contact_attributes[:email]) if contact_attributes[:email].present?
contact
end
def build_contact_inbox
ActiveRecord::Base.transaction do
contact = find_contact || create_contact
contact_inbox = create_contact_inbox(contact)
update_contact_avatar(contact)
contact_inbox
rescue StandardError => e
Rails.logger e
Rails.logger.info e
end
end
end
@@ -0,0 +1,142 @@
# This class creates both outgoing messages from chatwoot and echo outgoing messages based on the flag `outgoing_echo`
# Assumptions
# 1. Incase of an outgoing message which is echo, source_id will NOT be nil,
# based on this we are showing "not sent from chatwoot" message in frontend
# Hence there is no need to set user_id in message for outgoing echo messages.
class Messages::Facebook::MessageBuilder
attr_reader :response
def initialize(response, inbox, outgoing_echo: false)
@response = response
@inbox = inbox
@outgoing_echo = outgoing_echo
@sender_id = (@outgoing_echo ? @response.recipient_id : @response.sender_id)
@message_type = (@outgoing_echo ? :outgoing : :incoming)
end
def perform
ActiveRecord::Base.transaction do
build_contact
build_message
end
rescue StandardError => e
Raven.capture_exception(e)
true
end
private
def contact
@contact ||= @inbox.contact_inboxes.find_by(source_id: @sender_id)&.contact
end
def build_contact
return if contact.present?
@contact = Contact.create!(contact_params.except(:remote_avatar_url))
ContactAvatarJob.perform_later(@contact, contact_params[:remote_avatar_url]) if contact_params[:remote_avatar_url]
@contact_inbox = ContactInbox.create(contact: contact, inbox: @inbox, source_id: @sender_id)
end
def build_message
@message = conversation.messages.create!(message_params)
(response.attachments || []).each do |attachment|
attachment_obj = @message.attachments.new(attachment_params(attachment).except(:remote_file_url))
attachment_obj.save!
attach_file(attachment_obj, attachment_params(attachment)[:remote_file_url]) if attachment_params(attachment)[:remote_file_url]
end
end
def attach_file(attachment, file_url)
file_resource = LocalResource.new(file_url)
attachment.file.attach(io: file_resource.file, filename: file_resource.filename, content_type: file_resource.encoding)
rescue *ExceptionList::URI_EXCEPTIONS => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def conversation
@conversation ||= Conversation.find_by(conversation_params) || build_conversation
end
def build_conversation
@contact_inbox ||= contact.contact_inboxes.find_by!(source_id: @sender_id)
Conversation.create!(conversation_params.merge(
contact_inbox_id: @contact_inbox.id
))
end
def attachment_params(attachment)
file_type = attachment['type'].to_sym
params = { file_type: file_type, account_id: @message.account_id }
if [:image, :file, :audio, :video].include? file_type
params.merge!(file_type_params(attachment))
elsif file_type == :location
params.merge!(location_params(attachment))
elsif file_type == :fallback
params.merge!(fallback_params(attachment))
end
params
end
def file_type_params(attachment)
{
external_url: attachment['payload']['url'],
remote_file_url: attachment['payload']['url']
}
end
def location_params(attachment)
lat = attachment['payload']['coordinates']['lat']
long = attachment['payload']['coordinates']['long']
{
external_url: attachment['url'],
coordinates_lat: lat,
coordinates_long: long,
fallback_title: attachment['title']
}
end
def fallback_params(attachment)
{
fallback_title: attachment['title'],
external_url: attachment['url']
}
end
def conversation_params
{
account_id: @inbox.account_id,
inbox_id: @inbox.id,
contact_id: contact.id
}
end
def message_params
{
account_id: conversation.account_id,
inbox_id: conversation.inbox_id,
message_type: @message_type,
content: response.content,
source_id: response.identifier,
sender: @outgoing_echo ? nil : contact
}
end
def contact_params
begin
k = Koala::Facebook::API.new(@inbox.channel.page_access_token) if @inbox.facebook?
result = k.get_object(@sender_id) || {}
rescue StandardError => e
result = {}
Raven.capture_exception(e)
end
{
name: "#{result['first_name'] || 'John'} #{result['last_name'] || 'Doe'}",
account_id: @inbox.account_id,
remote_avatar_url: result['profile_pic'] || ''
}
end
end
@@ -1,2 +0,0 @@
class Messages::IncomingMessageBuilder < Messages::MessageBuilder
end
+38 -117
View File
@@ -1,138 +1,59 @@
# This class creates both outgoing messages from chatwoot and echo outgoing messages based on the flag `outgoing_echo`
# Assumptions
# 1. Incase of an outgoing message which is echo, source_id will NOT be nil,
# based on this we are showing "not sent from chatwoot" message in frontend
# Hence there is no need to set user_id in message for outgoing echo messages.
class Messages::MessageBuilder
attr_reader :response
include ::FileTypeHelper
attr_reader :message
def initialize(response, inbox, outgoing_echo = false)
@response = response
@inbox = inbox
@sender_id = (outgoing_echo ? @response.recipient_id : @response.sender_id)
@message_type = (outgoing_echo ? :outgoing : :incoming)
def initialize(user, conversation, params)
@params = params
@private = params[:private] || false
@conversation = conversation
@user = user
@message_type = params[:message_type] || 'outgoing'
@items = params.to_unsafe_h&.dig(:content_attributes, :items)
@attachments = params[:attachments]
@in_reply_to = params.to_unsafe_h&.dig(:content_attributes, :in_reply_to)
end
def perform
ActiveRecord::Base.transaction do
build_contact
build_message
@message = @conversation.messages.build(message_params)
if @attachments.present?
@attachments.each do |uploaded_attachment|
attachment = @message.attachments.new(
account_id: @message.account_id,
file_type: file_type(uploaded_attachment&.content_type)
)
attachment.file.attach(uploaded_attachment)
end
end
rescue StandardError => e
Raven.capture_exception(e)
true
@message.save
@message
end
private
def contact
@contact ||= @inbox.contact_inboxes.find_by(source_id: @sender_id)&.contact
end
def build_contact
return if contact.present?
@contact = Contact.create!(contact_params.except(:remote_avatar_url))
ContactAvatarJob.perform_later(@contact, contact_params[:remote_avatar_url]) if contact_params[:remote_avatar_url]
@contact_inbox = ContactInbox.create(contact: contact, inbox: @inbox, source_id: @sender_id)
end
def build_message
@message = conversation.messages.create!(message_params)
(response.attachments || []).each do |attachment|
attachment_obj = @message.attachments.new(attachment_params(attachment).except(:remote_file_url))
attachment_obj.save!
attach_file(attachment_obj, attachment_params(attachment)[:remote_file_url]) if attachment_params(attachment)[:remote_file_url]
end
end
def attach_file(attachment, file_url)
file_resource = LocalResource.new(file_url)
attachment.file.attach(io: file_resource.file, filename: file_resource.tmp_filename, content_type: file_resource.encoding)
end
def conversation
@conversation ||= Conversation.find_by(conversation_params) || build_conversation
end
def build_conversation
@contact_inbox ||= contact.contact_inboxes.find_by!(source_id: @sender_id)
Conversation.create!(conversation_params.merge(
contact_inbox_id: @contact_inbox.id
))
end
def attachment_params(attachment)
file_type = attachment['type'].to_sym
params = { file_type: file_type, account_id: @message.account_id }
if [:image, :file, :audio, :video].include? file_type
params.merge!(file_type_params(attachment))
elsif file_type == :location
params.merge!(location_params(attachment))
elsif file_type == :fallback
params.merge!(fallback_params(attachment))
def message_type
if @conversation.inbox.channel_type != 'Channel::Api' && @message_type == 'incoming'
raise StandardError, 'Incoming messages are only allowed in Api inboxes'
end
params
@message_type
end
def file_type_params(attachment)
{
external_url: attachment['payload']['url'],
remote_file_url: attachment['payload']['url']
}
end
def location_params(attachment)
lat = attachment['payload']['coordinates']['lat']
long = attachment['payload']['coordinates']['long']
{
external_url: attachment['url'],
coordinates_lat: lat,
coordinates_long: long,
fallback_title: attachment['title']
}
end
def fallback_params(attachment)
{
fallback_title: attachment['title'],
external_url: attachment['url']
}
end
def conversation_params
{
account_id: @inbox.account_id,
inbox_id: @inbox.id,
contact_id: contact.id
}
def sender
message_type == 'outgoing' ? @user : @conversation.contact
end
def message_params
{
account_id: conversation.account_id,
inbox_id: conversation.inbox_id,
message_type: @message_type,
content: response.content,
source_id: response.identifier
}
end
def contact_params
begin
k = Koala::Facebook::API.new(@inbox.channel.page_access_token) if @inbox.facebook?
result = k.get_object(@sender_id) || {}
rescue Exception => e
result = {}
Raven.capture_exception(e)
end
{
name: "#{result['first_name'] || 'John'} #{result['last_name'] || 'Doe'}",
account_id: @inbox.account_id,
remote_avatar_url: result['profile_pic'] || ''
account_id: @conversation.account_id,
inbox_id: @conversation.inbox_id,
message_type: message_type,
content: @params[:content],
private: @private,
sender: sender,
content_type: @params[:content_type],
items: @items,
in_reply_to: @in_reply_to,
echo_id: @params[:echo_id]
}
end
end
@@ -1,2 +0,0 @@
class Messages::Outgoing::EchoBuilder < ::Messages::MessageBuilder
end
@@ -1,46 +0,0 @@
class Messages::Outgoing::NormalBuilder
include ::FileTypeHelper
attr_reader :message
def initialize(user, conversation, params)
@content = params[:content]
@private = params[:private] || false
@conversation = conversation
@user = user
@fb_id = params[:fb_id]
@content_type = params[:content_type]
@items = params.to_unsafe_h&.dig(:content_attributes, :items)
@attachments = params[:attachments]
end
def perform
@message = @conversation.messages.build(message_params)
if @attachments.present?
@attachments.each do |uploaded_attachment|
attachment = @message.attachments.new(
account_id: @message.account_id,
file_type: file_type(uploaded_attachment&.content_type)
)
attachment.file.attach(uploaded_attachment)
end
end
@message.save
@message
end
private
def message_params
{
account_id: @conversation.account_id,
inbox_id: @conversation.inbox_id,
message_type: :outgoing,
content: @content,
private: @private,
user_id: @user&.id,
source_id: @fb_id,
content_type: @content_type,
items: @items
}
end
end
@@ -12,6 +12,8 @@ class NotificationSubscriptionBuilder
def identifier
@identifier ||= params[:subscription_attributes][:endpoint] if params[:subscription_type] == 'browser_push'
@identifier ||= params[:subscription_attributes][:device_id] if params[:subscription_type] == 'fcm'
@identifier
end
def identifier_subscription
+41 -4
View File
@@ -1,10 +1,47 @@
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from params[:pubsub_token]
::OnlineStatusTracker.add_subscription(params[:pubsub_token])
ensure_stream
current_user
current_account
update_subscription
broadcast_presence
end
def unsubscribed
::OnlineStatusTracker.remove_subscription(params[:pubsub_token])
def update_presence
update_subscription
broadcast_presence
end
private
def broadcast_presence
data = { account_id: @current_account.id, users: ::OnlineStatusTracker.get_available_users(@current_account.id) }
data[:contacts] = ::OnlineStatusTracker.get_available_contacts(@current_account.id) if @current_user.is_a? User
ActionCable.server.broadcast(@pubsub_token, { event: 'presence.update', data: data })
end
def ensure_stream
@pubsub_token = params[:pubsub_token]
stream_from @pubsub_token
end
def update_subscription
::OnlineStatusTracker.update_presence(@current_account.id, @current_user.class.name, @current_user.id)
end
def current_user
@current_user ||= if params[:user_id].blank?
Contact.find_by!(pubsub_token: @pubsub_token)
else
User.find_by!(pubsub_token: @pubsub_token, id: params[:user_id])
end
end
def current_account
@current_account ||= if @current_user.is_a? Contact
@current_user.account
else
@current_user.accounts.find(params[:account_id])
end
end
end
+3 -5
View File
@@ -11,11 +11,9 @@ class Api::BaseController < ApplicationController
request.headers[:api_access_token].present? || request.headers[:HTTP_API_ACCESS_TOKEN].present?
end
def set_conversation
@conversation ||= current_account.conversations.find_by(display_id: params[:conversation_id])
end
def check_authorization(model = nil)
model ||= controller_name.classify.constantize
def check_billing_enabled
raise ActionController::RoutingError, 'Not Found' unless ENV['BILLING_ENABLED']
authorize(model)
end
end
@@ -1,10 +1,10 @@
class Api::V1::Accounts::Actions::ContactMergesController < Api::BaseController
class Api::V1::Accounts::Actions::ContactMergesController < Api::V1::Accounts::BaseController
before_action :set_base_contact, only: [:create]
before_action :set_mergee_contact, only: [:create]
def create
contact_merge_action = ContactMergeAction.new(
account: current_account,
account: Current.account,
base_contact: @base_contact,
mergee_contact: @mergee_contact
)
@@ -23,6 +23,6 @@ class Api::V1::Accounts::Actions::ContactMergesController < Api::BaseController
end
def contacts
@contacts ||= current_account.contacts
@contacts ||= Current.account.contacts
end
end
@@ -1,4 +1,4 @@
class Api::V1::Accounts::AgentsController < Api::BaseController
class Api::V1::Accounts::AgentsController < Api::V1::Accounts::BaseController
before_action :fetch_agent, except: [:create, :index]
before_action :check_authorization
before_action :find_user, only: [:create]
@@ -10,24 +10,24 @@ class Api::V1::Accounts::AgentsController < Api::BaseController
end
def destroy
@agent.account_user.destroy
@agent.current_account_user.destroy
head :ok
end
def update
@agent.update!(agent_params.except(:role))
@agent.account_user.update!(role: agent_params[:role]) if agent_params[:role]
render 'api/v1/models/user.json', locals: { resource: @agent }
@agent.current_account_user.update!(role: agent_params[:role]) if agent_params[:role]
render partial: 'api/v1/models/agent.json.jbuilder', locals: { resource: @agent }
end
def create
render 'api/v1/models/user.json', locals: { resource: @user }
render partial: 'api/v1/models/agent.json.jbuilder', locals: { resource: @user }
end
private
def check_authorization
authorize(User)
super(User)
end
def fetch_agent
@@ -46,7 +46,7 @@ class Api::V1::Accounts::AgentsController < Api::BaseController
def save_account_user
AccountUser.create!(
account_id: current_account.id,
account_id: Current.account.id,
user_id: @user.id,
role: new_agent_params[:role],
inviter_id: current_user.id
@@ -64,6 +64,6 @@ class Api::V1::Accounts::AgentsController < Api::BaseController
end
def agents
@agents ||= current_account.users
@agents ||= Current.account.users.order_by_full_name.includes({ avatar_attachment: [:blob] })
end
end
@@ -0,0 +1,32 @@
class Api::V1::Accounts::BaseController < Api::BaseController
include SwitchLocale
before_action :current_account
around_action :switch_locale_using_account_locale
private
def current_account
@current_account ||= ensure_current_account
Current.account = @current_account
end
def ensure_current_account
account = Account.find(params[:account_id])
if current_user
account_accessible_for_user?(account)
elsif @resource&.is_a?(AgentBot)
account_accessible_for_bot?(account)
end
account
end
def account_accessible_for_user?(account)
@current_account_user = account.account_users.find_by(user_id: current_user.id)
Current.account_user = @current_account_user
render_unauthorized('You are not authorized to access this account') unless @current_account_user
end
def account_accessible_for_bot?(account)
render_unauthorized('You are not authorized to access this account') unless @resource.agent_bot_inboxes.find_by(account_id: account.id)
end
end
@@ -1,4 +1,4 @@
class Api::V1::Accounts::CallbacksController < Api::BaseController
class Api::V1::Accounts::CallbacksController < Api::V1::Accounts::BaseController
before_action :inbox, only: [:reauthorize_page]
def register_facebook_page
@@ -7,14 +7,14 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
page_id = params[:page_id]
inbox_name = params[:inbox_name]
ActiveRecord::Base.transaction do
facebook_channel = current_account.facebook_pages.create!(
facebook_channel = Current.account.facebook_pages.create!(
page_id: page_id, user_access_token: user_access_token,
page_access_token: page_access_token
)
@facebook_inbox = current_account.inboxes.create!(name: inbox_name, channel: facebook_channel)
@facebook_inbox = Current.account.inboxes.create!(name: inbox_name, channel: facebook_channel)
set_avatar(@facebook_inbox, page_id)
rescue StandardError => e
Rails.logger e
Rails.logger.info e
end
end
@@ -22,7 +22,7 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
@page_details = mark_already_existing_facebook_pages(fb_object.get_connections('me', 'accounts'))
end
# get params[:inbox_id], current_account, params[:omniauth_token]
# get params[:inbox_id], current_account. params[:omniauth_token]
def reauthorize_page
if @inbox&.facebook?
fb_page_id = @inbox.channel.page_id
@@ -30,7 +30,7 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
if (page_detail = (page_details || []).detect { |page| fb_page_id == page['id'] })
update_fb_page(fb_page_id, page_detail['access_token'])
return head :ok
render and return
end
end
@@ -40,17 +40,17 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
private
def inbox
@inbox = current_account.inboxes.find_by(id: params[:inbox_id])
@inbox = Current.account.inboxes.find_by(id: params[:inbox_id])
end
def update_fb_page(fb_page_id, access_token)
get_fb_page(fb_page_id)&.update!(
user_access_token: @user_access_token, page_access_token: access_token
)
fb_page = get_fb_page(fb_page_id)
fb_page&.update!(user_access_token: @user_access_token, page_access_token: access_token)
fb_page&.reauthorized!
end
def get_fb_page(fb_page_id)
current_account.facebook_pages.find_by(page_id: fb_page_id)
Current.account.facebook_pages.find_by(page_id: fb_page_id)
end
def fb_object
@@ -62,14 +62,14 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
koala = Koala::Facebook::OAuth.new(ENV['FB_APP_ID'], ENV['FB_APP_SECRET'])
koala.exchange_access_token_info(omniauth_token)['access_token']
rescue StandardError => e
Rails.logger e
Rails.logger.info e
end
def mark_already_existing_facebook_pages(data)
return [] if data.empty?
data.inject([]) do |result, page_detail|
page_detail[:exists] = current_account.facebook_pages.exists?(page_id: page_detail['id']) ? true : false
page_detail[:exists] = Current.account.facebook_pages.exists?(page_id: page_detail['id']) ? true : false
result << page_detail
end
end
@@ -81,6 +81,8 @@ class Api::V1::Accounts::CallbacksController < Api::BaseController
avatar_resource = LocalResource.new(uri)
facebook_inbox.avatar.attach(io: avatar_resource.file, filename: avatar_resource.tmp_filename, content_type: avatar_resource.encoding)
rescue *ExceptionList::URI_EXCEPTIONS => e
Rails.logger.info "invalid url #{file_url} : #{e.message}"
end
def get_avatar_url(page_id)
@@ -1,4 +1,4 @@
class Api::V1::Accounts::CannedResponsesController < Api::BaseController
class Api::V1::Accounts::CannedResponsesController < Api::V1::Accounts::BaseController
before_action :fetch_canned_response, only: [:update, :destroy]
def index
@@ -6,7 +6,7 @@ class Api::V1::Accounts::CannedResponsesController < Api::BaseController
end
def create
@canned_response = current_account.canned_responses.new(canned_response_params)
@canned_response = Current.account.canned_responses.new(canned_response_params)
@canned_response.save!
render json: @canned_response
end
@@ -24,7 +24,7 @@ class Api::V1::Accounts::CannedResponsesController < Api::BaseController
private
def fetch_canned_response
@canned_response = current_account.canned_responses.find(params[:id])
@canned_response = Current.account.canned_responses.find(params[:id])
end
def canned_response_params
@@ -33,9 +33,9 @@ class Api::V1::Accounts::CannedResponsesController < Api::BaseController
def canned_responses
if params[:search]
current_account.canned_responses.where('short_code ILIKE ?', "#{params[:search]}%")
Current.account.canned_responses.where('short_code ILIKE ?', "#{params[:search]}%")
else
current_account.canned_responses
Current.account.canned_responses
end
end
end
@@ -1,4 +1,4 @@
class Api::V1::Accounts::Channels::TwilioChannelsController < Api::BaseController
class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts::BaseController
before_action :authorize_request
def create
@@ -37,13 +37,13 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::BaseControlle
end
def build_inbox
@twilio_channel = current_account.twilio_sms.create!(
@twilio_channel = Current.account.twilio_sms.create!(
account_sid: permitted_params[:account_sid],
auth_token: permitted_params[:auth_token],
phone_number: phone_number,
medium: medium
)
@inbox = current_account.inboxes.create(
@inbox = Current.account.inboxes.create(
name: permitted_params[:name],
channel: @twilio_channel
)
@@ -0,0 +1,19 @@
class Api::V1::Accounts::Contacts::ContactInboxesController < Api::V1::Accounts::BaseController
before_action :ensure_contact
before_action :ensure_inbox, only: [:create]
def create
source_id = params[:source_id] || SecureRandom.uuid
@contact_inbox = ContactInbox.create!(contact: @contact, inbox: @inbox, source_id: source_id)
end
private
def ensure_inbox
@inbox = Current.account.inboxes.find(params[:inbox_id])
end
def ensure_contact
@contact = Current.account.contacts.find(params[:contact_id])
end
end
@@ -1,7 +1,7 @@
class Api::V1::Accounts::Contacts::ConversationsController < Api::BaseController
class Api::V1::Accounts::Contacts::ConversationsController < Api::V1::Accounts::BaseController
def index
@conversations = current_account.conversations.includes(
:assignee, :contact, :inbox
@conversations = Current.account.conversations.includes(
:assignee, :contact, :inbox, :taggings
).where(inbox_id: inbox_ids, contact_id: permitted_params[:contact_id])
end
@@ -9,7 +9,7 @@ class Api::V1::Accounts::Contacts::ConversationsController < Api::BaseController
def inbox_ids
if current_user.administrator?
current_account.inboxes.pluck(:id)
Current.account.inboxes.pluck(:id)
elsif current_user.agent?
current_user.assigned_inboxes.pluck(:id)
else
@@ -0,0 +1,13 @@
class Api::V1::Accounts::Contacts::LabelsController < Api::V1::Accounts::BaseController
include LabelConcern
private
def model
@model ||= Current.account.contacts.find(permitted_params[:contact_id])
end
def permitted_params
params.permit(:contact_id, labels: [])
end
end
@@ -1,40 +1,108 @@
class Api::V1::Accounts::ContactsController < Api::BaseController
class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
RESULTS_PER_PAGE = 15
protect_from_forgery with: :null_session
before_action :check_authorization
before_action :set_current_page, only: [:index, :active, :search]
before_action :fetch_contact, only: [:show, :update]
def index
@contacts = current_account.contacts
@contacts_count = resolved_contacts.count
@contacts = fetch_contact_last_seen_at(resolved_contacts)
end
def search
render json: { error: 'Specify search string with parameter q' }, status: :unprocessable_entity if params[:q].blank? && return
contacts = resolved_contacts.where(
'name ILIKE :search OR email ILIKE :search OR phone_number ILIKE :search',
search: "%#{params[:q]}%"
)
@contacts_count = contacts.count
@contacts = fetch_contact_last_seen_at(contacts)
end
def import
ActiveRecord::Base.transaction do
import = Current.account.data_imports.create!(data_type: 'contacts')
import.import_file.attach(params[:import_file])
end
head :ok
end
# returns online contacts
def active
contacts = Current.account.contacts.where(id: ::OnlineStatusTracker
.get_available_contact_ids(Current.account.id))
@contacts_count = contacts.count
@contacts = contacts.page(@current_page)
end
def show; end
def create
@contact = Contact.new(contact_create_params)
@contact.save!
render json: @contact
ActiveRecord::Base.transaction do
@contact = Current.account.contacts.new(contact_params)
@contact.save!
@contact_inbox = build_contact_inbox
end
end
def update
@contact.update!(contact_params)
@contact.assign_attributes(contact_update_params)
@contact.save!
rescue ActiveRecord::RecordInvalid => e
render json: {
message: e.record.errors.full_messages.join(', '),
contact: Current.account.contacts.find_by(email: contact_params[:email])
}, status: :unprocessable_entity
end
private
def check_authorization
authorize(Contact)
def resolved_contacts
@resolved_contacts ||= Current.account.contacts
.where.not(email: [nil, ''])
.or(Current.account.contacts.where.not(phone_number: [nil, '']))
.order('LOWER(name)')
end
def set_current_page
@current_page = params[:page] || 1
end
def fetch_contact_last_seen_at(contacts)
contacts.left_outer_joins(:conversations)
.select('contacts.*, COUNT(conversations.id) as conversations_count, MAX(conversations.contact_last_seen_at) as last_seen_at')
.group('contacts.id')
.includes([{ avatar_attachment: [:blob] }, { contact_inboxes: [:inbox] }])
.page(@current_page).per(RESULTS_PER_PAGE)
end
def build_contact_inbox
return if params[:inbox_id].blank?
inbox = Current.account.inboxes.find(params[:inbox_id])
source_id = params[:source_id] || SecureRandom.uuid
ContactInbox.create(contact: @contact, inbox: inbox, source_id: source_id)
end
def contact_params
params.require(:contact).permit(:name, :email, :phone_number)
params.require(:contact).permit(:name, :email, :phone_number, additional_attributes: {}, custom_attributes: {})
end
def contact_custom_attributes
return @contact.custom_attributes.merge(contact_params[:custom_attributes]) if contact_params[:custom_attributes]
@contact.custom_attributes
end
def contact_update_params
# we want the merged custom attributes not the original one
contact_params.except(:custom_attributes).merge({ custom_attributes: contact_custom_attributes })
end
def fetch_contact
@contact = current_account.contacts.find(params[:id])
end
def contact_create_params
params.require(:contact).permit(:account_id, :inbox_id).merge!(name: SecureRandom.hex)
@contact = Current.account.contacts.includes(contact_inboxes: [:inbox]).find(params[:id])
end
end
@@ -1,11 +1,20 @@
class Api::V1::Accounts::Conversations::AssignmentsController < Api::BaseController
before_action :set_conversation, only: [:create]
# assign agent to a conversation
class Api::V1::Accounts::Conversations::AssignmentsController < Api::V1::Accounts::Conversations::BaseController
# assigns agent/team to a conversation
def create
set_assignee
render json: @assignee
end
private
def set_assignee
# if params[:assignee_id] is not a valid id, it will set to nil, hence unassigning the conversation
assignee = current_account.users.find_by(id: params[:assignee_id])
@conversation.update_assignee(assignee)
render json: assignee
if params.key?(:assignee_id)
@assignee = Current.account.users.find_by(id: params[:assignee_id])
@conversation.update_assignee(@assignee)
elsif params.key?(:team_id)
@assignee = Current.account.teams.find_by(id: params[:team_id])
@conversation.update!(team: @assignee)
end
end
end
@@ -0,0 +1,9 @@
class Api::V1::Accounts::Conversations::BaseController < Api::V1::Accounts::BaseController
before_action :conversation
private
def conversation
@conversation ||= Current.account.conversations.find_by(display_id: params[:conversation_id])
end
end
@@ -1,13 +1,13 @@
class Api::V1::Accounts::Conversations::LabelsController < Api::BaseController
before_action :set_conversation, only: [:create, :index]
class Api::V1::Accounts::Conversations::LabelsController < Api::V1::Accounts::Conversations::BaseController
include LabelConcern
def create
@conversation.update_labels(params[:labels])
@labels = @conversation.label_list
private
def model
@model ||= @conversation
end
# all labels of the current conversation
def index
@labels = @conversation.label_list
def permitted_params
params.permit(:conversation_id, labels: [])
end
end
@@ -1,18 +1,34 @@
class Api::V1::Accounts::Conversations::MessagesController < Api::BaseController
before_action :set_conversation, only: [:index, :create]
class Api::V1::Accounts::Conversations::MessagesController < Api::V1::Accounts::Conversations::BaseController
def index
@messages = message_finder.perform
end
def create
mb = Messages::Outgoing::NormalBuilder.new(current_user, @conversation, params)
user = current_user || @resource
mb = Messages::MessageBuilder.new(user, @conversation, params)
@message = mb.perform
rescue StandardError => e
render_could_not_create_error(e.message)
end
def destroy
ActiveRecord::Base.transaction do
message.update!(content: I18n.t('conversations.messages.deleted'), deleted: true)
message.attachments.destroy_all
end
end
private
def message
@message ||= @conversation.messages.find(permitted_params[:id])
end
def message_finder
@message_finder ||= MessageFinder.new(@conversation, params)
end
def permitted_params
params.permit(:id)
end
end
@@ -1,5 +1,6 @@
class Api::V1::Accounts::ConversationsController < Api::BaseController
class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseController
include Events::Types
before_action :conversation, except: [:index]
before_action :contact_inbox, only: [:create]
@@ -14,29 +15,55 @@ class Api::V1::Accounts::ConversationsController < Api::BaseController
@conversations_count = result[:count]
end
def search
result = conversation_finder.perform
@conversations = result[:conversations]
@conversations_count = result[:count]
end
def create
@conversation = ::Conversation.create!(conversation_params)
end
def show; end
def mute
@conversation.mute!
head :ok
end
def unmute
@conversation.unmute!
head :ok
end
def transcript
ConversationReplyMailer.conversation_transcript(@conversation, params[:email])&.deliver_later if params[:email].present?
head :ok
end
def toggle_status
@status = @conversation.toggle_status
if params[:status]
@conversation.status = params[:status]
@status = @conversation.save
else
@status = @conversation.toggle_status
end
end
def toggle_typing_status
if params[:typing_status] == 'on'
case params[:typing_status]
when 'on'
trigger_typing_event(CONVERSATION_TYPING_ON)
elsif params[:typing_status] == 'off'
when 'off'
trigger_typing_event(CONVERSATION_TYPING_OFF)
end
head :ok
end
def update_last_seen
@conversation.agent_last_seen_at = parsed_last_seen_at
@conversation.agent_last_seen_at = DateTime.now.utc
@conversation.save!
head :ok
end
private
@@ -46,12 +73,8 @@ class Api::V1::Accounts::ConversationsController < Api::BaseController
Rails.configuration.dispatcher.dispatch(event, Time.zone.now, conversation: @conversation, user: user)
end
def parsed_last_seen_at
DateTime.strptime(params[:agent_last_seen_at].to_s, '%s')
end
def conversation
@conversation ||= current_account.conversations.find_by(display_id: params[:id])
@conversation ||= Current.account.conversations.find_by(display_id: params[:id])
end
def contact_inbox
@@ -60,10 +83,11 @@ class Api::V1::Accounts::ConversationsController < Api::BaseController
def conversation_params
{
account_id: current_account.id,
account_id: Current.account.id,
inbox_id: @contact_inbox.inbox_id,
contact_id: @contact_inbox.contact_id,
contact_inbox_id: @contact_inbox.id
contact_inbox_id: @contact_inbox.id,
additional_attributes: params[:additional_attributes]
}
end
@@ -1,4 +1,4 @@
class Api::V1::Accounts::FacebookIndicatorsController < Api::BaseController
class Api::V1::Accounts::FacebookIndicatorsController < Api::V1::Accounts::BaseController
before_action :set_access_token
around_action :handle_with_exception
@@ -38,7 +38,7 @@ class Api::V1::Accounts::FacebookIndicatorsController < Api::BaseController
end
def inbox
@inbox ||= current_account.inboxes.find(permitted_params[:inbox_id])
@inbox ||= Current.account.inboxes.find(permitted_params[:inbox_id])
end
def set_access_token
@@ -1,4 +1,4 @@
class Api::V1::Accounts::InboxMembersController < Api::BaseController
class Api::V1::Accounts::InboxMembersController < Api::V1::Accounts::BaseController
before_action :fetch_inbox, only: [:create, :show]
before_action :current_agents_ids, only: [:create]
@@ -12,7 +12,7 @@ class Api::V1::Accounts::InboxMembersController < Api::BaseController
end
def show
@agents = current_account.users.where(id: @inbox.members.pluck(:user_id))
@agents = Current.account.users.where(id: @inbox.members.select(:user_id))
end
private
@@ -22,9 +22,10 @@ class Api::V1::Accounts::InboxMembersController < Api::BaseController
# get the list of user_ids from params
# the missing ones are the agents which are to be deleted from the inbox
# the new ones are the agents which are to be added to the inbox
agents_to_be_added_ids.each { |user_id| @inbox.add_member(user_id) }
agents_to_be_removed_ids.each { |user_id| @inbox.remove_member(user_id) }
ActiveRecord::Base.transaction do
agents_to_be_added_ids.each { |user_id| @inbox.add_member(user_id) }
agents_to_be_removed_ids.each { |user_id| @inbox.remove_member(user_id) }
end
end
def agents_to_be_added_ids
@@ -40,6 +41,6 @@ class Api::V1::Accounts::InboxMembersController < Api::BaseController
end
def fetch_inbox
@inbox = current_account.inboxes.find(params[:inbox_id])
@inbox = Current.account.inboxes.find(params[:inbox_id])
end
end
@@ -1,16 +1,21 @@
class Api::V1::Accounts::InboxesController < Api::BaseController
before_action :check_authorization
class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
before_action :fetch_inbox, except: [:index, :create]
before_action :fetch_agent_bot, only: [:set_agent_bot]
before_action :check_authorization
def index
@inboxes = policy_scope(current_account.inboxes)
@inboxes = policy_scope(Current.account.inboxes.order_by_name.includes(:channel, { avatar_attachment: [:blob] }))
end
def create
ActiveRecord::Base.transaction do
channel = web_widgets.create!(permitted_params[:channel].except(:type)) if permitted_params[:channel][:type] == 'web_widget'
@inbox = current_account.inboxes.build(name: permitted_params[:name], channel: channel)
channel = create_channel
@inbox = Current.account.inboxes.build(
name: permitted_params[:name],
greeting_message: permitted_params[:greeting_message],
greeting_enabled: permitted_params[:greeting_enabled],
channel: channel
)
@inbox.avatar.attach(permitted_params[:avatar])
@inbox.save!
end
@@ -18,7 +23,11 @@ class Api::V1::Accounts::InboxesController < Api::BaseController
def update
@inbox.update(inbox_update_params.except(:channel))
@inbox.channel.update!(inbox_update_params[:channel]) if @inbox.channel.is_a?(Channel::WebWidget) && inbox_update_params[:channel].present?
@inbox.update_working_hours(params.permit(working_hours: Inbox::OFFISABLE_ATTRS)[:working_hours]) if params[:working_hours]
return unless @inbox.channel.is_a?(Channel::WebWidget) && inbox_update_params[:channel].present?
@inbox.channel.update!(inbox_update_params[:channel])
update_channel_feature_flags
end
def set_agent_bot
@@ -40,27 +49,50 @@ class Api::V1::Accounts::InboxesController < Api::BaseController
private
def fetch_inbox
@inbox = current_account.inboxes.find(params[:id])
@inbox = Current.account.inboxes.find(params[:id])
end
def fetch_agent_bot
@agent_bot = AgentBot.find(params[:agent_bot]) if params[:agent_bot]
end
def web_widgets
current_account.web_widgets
def create_channel
case permitted_params[:channel][:type]
when 'web_widget'
Current.account.web_widgets.create!(permitted_params[:channel].except(:type))
when 'api'
Current.account.api_channels.create!(permitted_params[:channel].except(:type))
when 'email'
Current.account.email_channels.create!(permitted_params[:channel].except(:type))
end
end
def check_authorization
authorize(Inbox)
def update_channel_feature_flags
return unless inbox_update_params[:channel].key? :selected_feature_flags
@inbox.channel.selected_feature_flags = inbox_update_params[:channel][:selected_feature_flags]
@inbox.channel.save!
end
def permitted_params
params.permit(:id, :avatar, :name, channel: [:type, :website_url, :widget_color, :welcome_title, :welcome_tagline, :agent_away_message])
params.permit(:id, :avatar, :name, :greeting_message, :greeting_enabled, channel:
[:type, :website_url, :widget_color, :welcome_title, :welcome_tagline, :webhook_url, :email, :reply_time])
end
def inbox_update_params
params.permit(:enable_auto_assignment, :name, :avatar, channel: [:website_url, :widget_color, :welcome_title,
:welcome_tagline, :agent_away_message])
params.permit(:enable_auto_assignment, :name, :avatar, :greeting_message, :greeting_enabled,
:working_hours_enabled, :out_of_office_message, :timezone,
channel: [
:website_url,
:widget_color,
:welcome_title,
:welcome_tagline,
:webhook_url,
:email,
:reply_time,
:pre_chat_form_enabled,
{ pre_chat_form_options: [:pre_chat_message, :require_email] },
{ selected_feature_flags: [] }
])
end
end
@@ -0,0 +1,18 @@
class Api::V1::Accounts::Integrations::AppsController < Api::V1::Accounts::BaseController
before_action :fetch_apps, only: [:index]
before_action :fetch_app, only: [:show]
def index; end
def show; end
private
def fetch_apps
@apps = Integrations::App.all.select(&:active?)
end
def fetch_app
@app = Integrations::App.find(id: params[:id])
end
end
@@ -0,0 +1,40 @@
class Api::V1::Accounts::Integrations::SlackController < Api::V1::Accounts::BaseController
before_action :fetch_hook, only: [:update, :destroy]
def create
ActiveRecord::Base.transaction do
builder = Integrations::Slack::HookBuilder.new(
account: Current.account,
code: params[:code],
inbox_id: params[:inbox_id]
)
@hook = builder.perform
create_chatwoot_slack_channel
end
end
def update
create_chatwoot_slack_channel
render json: @hook
end
def destroy
@hook.destroy
head :ok
end
private
def fetch_hook
@hook = Integrations::Hook.where(account: Current.account).find_by(app_id: 'slack')
end
def create_chatwoot_slack_channel
channel = params[:channel] || 'customer-conversations'
builder = Integrations::Slack::ChannelBuilder.new(
hook: @hook, channel: channel
)
builder.perform
end
end
@@ -0,0 +1,9 @@
class Api::V1::Accounts::Kbase::BaseController < Api::V1::Accounts::BaseController
before_action :portal
private
def portal
@portal ||= Current.account.kbase_portals.find_by(id: params[:portal_id])
end
end
@@ -0,0 +1,32 @@
class Api::V1::Accounts::Kbase::CategoriesController < Api::V1::Accounts::Kbase::BaseController
before_action :fetch_category, except: [:index, :create]
def index
@categories = @portal.categories
end
def create
@category = @portal.categories.create!(category_params)
end
def update
@category.update!(category_params)
end
def destroy
@category.destroy
head :ok
end
private
def fetch_category
@category = @portal.categories.find(params[:id])
end
def category_params
params.require(:category).permit(
:name, :description, :position
)
end
end
@@ -0,0 +1,32 @@
class Api::V1::Accounts::Kbase::PortalsController < Api::V1::Accounts::Kbase::BaseController
before_action :fetch_portal, except: [:index, :create]
def index
@portals = Current.account.kbase_portals
end
def create
@portal = Current.account.kbase_portals.create!(portal_params)
end
def update
@portal.update!(portal_params)
end
def destroy
@portal.destroy
head :ok
end
private
def fetch_portal
@portal = current_account.kbase_portals.find(params[:id])
end
def portal_params
params.require(:portal).permit(
:account_id, :color, :custom_domain, :header_text, :homepage_link, :name, :page_title, :slug
)
end
end
@@ -1,10 +1,34 @@
class Api::V1::Accounts::LabelsController < Api::BaseController
# list all labels in account
class Api::V1::Accounts::LabelsController < Api::V1::Accounts::BaseController
before_action :current_account
before_action :fetch_label, except: [:index, :create]
before_action :check_authorization
def index
@labels = current_account.all_conversation_tags
@labels = policy_scope(Current.account.labels)
end
def most_used
@labels = ActsAsTaggableOn::Tag.most_used(params[:count] || 10)
def show; end
def create
@label = Current.account.labels.create!(permitted_params)
end
def update
@label.update!(permitted_params)
end
def destroy
@label.destroy
head :ok
end
private
def fetch_label
@label = Current.account.labels.find(params[:id])
end
def permitted_params
params.require(:label).permit(:title, :description, :color, :show_on_sidebar)
end
end
@@ -1,4 +1,4 @@
class Api::V1::Accounts::NotificationSettingsController < Api::BaseController
class Api::V1::Accounts::NotificationSettingsController < Api::V1::Accounts::BaseController
before_action :set_user, :load_notification_setting
def show; end
@@ -16,7 +16,7 @@ class Api::V1::Accounts::NotificationSettingsController < Api::BaseController
end
def load_notification_setting
@notification_setting = @user.notification_settings.find_by(account_id: current_account.id)
@notification_setting = @user.notification_settings.find_by(account_id: Current.account.id)
end
def notification_setting_params
@@ -1,11 +1,27 @@
class Api::V1::Accounts::NotificationsController < Api::BaseController
protect_from_forgery with: :null_session
class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseController
RESULTS_PER_PAGE = 15
protect_from_forgery with: :null_session
before_action :fetch_notification, only: [:update]
before_action :set_primary_actor, only: [:read_all]
before_action :set_current_page, only: [:index]
def index
@notifications = current_user.notifications.where(account_id: current_account.id)
render json: @notifications
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
@count = notifications.count
@notifications = notifications.page(@current_page).per(RESULTS_PER_PAGE)
end
def read_all
# rubocop:disable Rails/SkipsModelValidations
if @primary_actor
current_user.notifications.where(account_id: current_account.id, primary_actor: @primary_actor, read_at: nil)
.update_all(read_at: DateTime.now.utc)
else
current_user.notifications.where(account_id: current_account.id, read_at: nil).update_all(read_at: DateTime.now.utc)
end
# rubocop:enable Rails/SkipsModelValidations
head :ok
end
def update
@@ -13,9 +29,29 @@ class Api::V1::Accounts::NotificationsController < Api::BaseController
render json: @notification
end
def unread_count
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
render json: @unread_count
end
private
def set_primary_actor
return unless params[:primary_actor_type]
return unless Notification::PRIMARY_ACTORS.include?(params[:primary_actor_type])
@primary_actor = params[:primary_actor_type].safe_constantize.find_by(id: params[:primary_actor_id])
end
def fetch_notification
@notification = current_user.notifications.find(params[:id])
end
def set_current_page
@current_page = params[:page] || 1
end
def notifications
@notifications ||= current_user.notifications.where(account_id: current_account.id)
end
end
@@ -1,13 +0,0 @@
class Api::V1::Accounts::SubscriptionsController < Api::BaseController
skip_before_action :check_subscription
before_action :check_billing_enabled
def index
render json: current_account.subscription_data
end
def status
render json: current_account.subscription.summary
end
end
@@ -0,0 +1,48 @@
class Api::V1::Accounts::TeamMembersController < Api::V1::Accounts::BaseController
before_action :fetch_team
before_action :check_authorization
def index
@team_members = @team.team_members.map(&:user)
end
def create
ActiveRecord::Base.transaction do
@team_members = params[:user_ids].map { |user_id| @team.add_member(user_id) }
end
end
def update
ActiveRecord::Base.transaction do
members_to_be_added_ids.each { |user_id| @team.add_member(user_id) }
members_to_be_removed_ids.each { |user_id| @team.remove_member(user_id) }
end
@team_members = @team.members
render action: 'create'
end
def destroy
ActiveRecord::Base.transaction do
params[:user_ids].map { |user_id| @team.remove_member(user_id) }
end
head :ok
end
private
def members_to_be_added_ids
params[:user_ids] - current_members_ids
end
def members_to_be_removed_ids
current_members_ids - params[:user_ids]
end
def current_members_ids
@current_members_ids ||= @team.members.pluck(:id)
end
def fetch_team
@team = Current.account.teams.find(params[:team_id])
end
end
@@ -0,0 +1,34 @@
class Api::V1::Accounts::TeamsController < Api::V1::Accounts::BaseController
before_action :fetch_team, only: [:show, :update, :destroy]
before_action :check_authorization
def index
@teams = Current.account.teams
end
def show; end
def create
@team = Current.account.teams.new(team_params)
@team.save!
end
def update
@team.update!(team_params)
end
def destroy
@team.destroy
head :ok
end
private
def fetch_team
@team = Current.account.teams.find(params[:id])
end
def team_params
params.require(:team).permit(:name, :description, :allow_auto_assign)
end
end
@@ -0,0 +1,29 @@
class Api::V1::Accounts::Twitter::AuthorizationsController < Api::V1::Accounts::BaseController
include TwitterConcern
before_action :check_authorization
def create
@response = twitter_client.request_oauth_token(url: twitter_callback_url)
if @response.status == '200'
::Redis::Alfred.setex(oauth_token, Current.account.id)
render json: { success: true, url: oauth_authorize_endpoint(oauth_token) }
else
render json: { success: false }, status: :unprocessable_entity
end
end
private
def oauth_token
parsed_body['oauth_token']
end
def oauth_authorize_endpoint(oauth_token)
"#{twitter_api_base_url}/oauth/authorize?oauth_token=#{oauth_token}"
end
def check_authorization
raise Pundit::NotAuthorizedError unless Current.account_user.administrator?
end
end
@@ -1,13 +1,13 @@
class Api::V1::Accounts::WebhooksController < Api::BaseController
class Api::V1::Accounts::WebhooksController < Api::V1::Accounts::BaseController
before_action :check_authorization
before_action :fetch_webhook, only: [:update, :destroy]
def index
@webhooks = current_account.webhooks
@webhooks = Current.account.webhooks
end
def create
@webhook = current_account.webhooks.new(webhook_params)
@webhook = Current.account.webhooks.new(webhook_params)
@webhook.save!
end
@@ -27,10 +27,6 @@ class Api::V1::Accounts::WebhooksController < Api::BaseController
end
def fetch_webhook
@webhook = current_account.webhooks.find(params[:id])
end
def check_authorization
authorize(Webhook)
@webhook = Current.account.webhooks.find(params[:id])
end
end
@@ -0,0 +1,18 @@
class Api::V1::Accounts::WorkingHoursController < Api::V1::Accounts::BaseController
before_action :check_authorization
before_action :fetch_webhook, only: [:update]
def update
@working_hour.update!(working_hour_params)
end
private
def working_hour_params
params.require(:working_hour).permit(:inbox_id, :open_hour, :open_minutes, :close_hour, :close_minutes, :closed_all_day)
end
def fetch_working_hour
@working_hour = Current.account.working_hours.find(params[:id])
end
end
@@ -1,12 +1,12 @@
class Api::V1::Accounts::AccountsController < Api::BaseController
class Api::V1::AccountsController < Api::BaseController
include AuthHelper
skip_before_action :verify_authenticity_token, only: [:create]
skip_before_action :authenticate_user!, :set_current_user, :check_subscription, :handle_with_exception,
skip_before_action :authenticate_user!, :set_current_user, :handle_with_exception,
only: [:create], raise: false
before_action :check_signup_enabled, only: [:create]
before_action :check_authorization, except: [:create]
before_action :fetch_account, except: [:create]
before_action :check_authorization, except: [:create]
rescue_from CustomExceptions::Account::InvalidEmail,
CustomExceptions::Account::UserExists,
@@ -14,41 +14,60 @@ class Api::V1::Accounts::AccountsController < Api::BaseController
with: :render_error_response
def create
@user = AccountBuilder.new(
@user, @account = AccountBuilder.new(
account_name: account_params[:account_name],
email: account_params[:email]
user_full_name: account_params[:user_full_name],
email: account_params[:email],
confirmed: confirmed?,
user: current_user
).perform
if @user
send_auth_headers(@user)
render 'devise/auth.json', locals: { resource: @user }
render 'api/v1/accounts/create.json', locals: { resource: @user }
else
render_error_response(CustomExceptions::Account::SignupFailed.new({}))
end
end
def show
@latest_chatwoot_version = ::Redis::Alfred.get(::Redis::Alfred::LATEST_CHATWOOT_VERSION)
render 'api/v1/accounts/show.json'
end
def update
@account.update!(account_params.slice(:name, :locale, :domain, :support_email, :domain_emails_enabled))
@account.update!(account_params.slice(:name, :locale, :domain, :support_email, :auto_resolve_duration))
end
def update_active_at
@current_account_user.active_at = Time.now.utc
@current_account_user.save!
head :ok
end
private
def check_authorization
authorize(Account)
def confirmed?
super_admin? && params[:confirmed]
end
def fetch_account
@account = current_user.accounts.find(params[:id])
@current_account_user = @account.account_users.find_by(user_id: current_user.id)
end
def account_params
params.permit(:account_name, :email, :name, :locale, :domain, :support_email, :domain_emails_enabled)
params.permit(:account_name, :email, :name, :locale, :domain, :support_email, :auto_resolve_duration, :user_full_name)
end
def check_signup_enabled
raise ActionController::RoutingError, 'Not Found' if ENV.fetch('ENABLE_ACCOUNT_SIGNUP', true) == 'false'
end
def pundit_user
{
user: current_user,
account: @account,
account_user: @current_account_user
}
end
end
@@ -1,6 +1,5 @@
class Api::V1::AgentBotsController < Api::BaseController
skip_before_action :authenticate_user!
skip_before_action :check_subscription
def index
render json: AgentBot.all
@@ -0,0 +1,7 @@
class Api::V1::Integrations::WebhooksController < ApplicationController
def create
builder = Integrations::Slack::IncomingMessageBuilder.new(params)
response = builder.perform
render json: response
end
end
+11 -2
View File
@@ -2,7 +2,7 @@ class Api::V1::ProfilesController < Api::BaseController
before_action :set_user
def show
render json: @user
render partial: 'api/v1/models/user.json.jbuilder', locals: { resource: @user }
end
def update
@@ -16,6 +16,15 @@ class Api::V1::ProfilesController < Api::BaseController
end
def profile_params
params.require(:profile).permit(:email, :name, :password, :password_confirmation, :avatar)
params.require(:profile).permit(
:email,
:name,
:display_name,
:password,
:password_confirmation,
:avatar,
:availability,
ui_settings: {}
)
end
end
@@ -1,18 +1,6 @@
class Api::V1::WebhooksController < ApplicationController
skip_before_action :authenticate_user!, raise: false
skip_before_action :set_current_user
skip_before_action :check_subscription
before_action :login_from_basic_auth, only: [:chargebee]
before_action :check_billing_enabled, only: [:chargebee]
def chargebee
chargebee_consumer.consume
head :ok
rescue StandardError => e
Raven.capture_exception(e)
head :ok
end
def twitter_crc
render json: { response_token: "sha256=#{twitter_client.generate_crc(params[:crc_token])}" }
@@ -34,16 +22,6 @@ class Api::V1::WebhooksController < ApplicationController
end
end
def login_from_basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == ENV['CHARGEBEE_WEBHOOK_USERNAME'] && password == ENV['CHARGEBEE_WEBHOOK_PASSWORD']
end
end
def chargebee_consumer
@chargebee_consumer ||= ::Webhooks::Chargebee.new(params)
end
def twitter_consumer
@twitter_consumer ||= ::Webhooks::Twitter.new(params)
end
@@ -1,30 +1,107 @@
class Api::V1::Widget::BaseController < ApplicationController
include SwitchLocale
before_action :set_web_widget
before_action :set_contact
private
def conversations
if @contact_inbox.hmac_verified?
verified_contact_inbox_ids = @contact.contact_inboxes.where(inbox_id: auth_token_params[:inbox_id], hmac_verified: true).map(&:id)
@conversations = @contact.conversations.where(contact_inbox_id: verified_contact_inbox_ids)
else
@conversations = @contact_inbox.conversations.where(inbox_id: auth_token_params[:inbox_id])
end
end
def conversation
@conversation ||= @contact_inbox.conversations.where(
inbox_id: auth_token_params[:inbox_id]
).last
@conversation ||= conversations.last
end
def auth_token_params
@auth_token_params ||= ::Widget::TokenService.new(token: request.headers[header_name]).decode_token
end
def header_name
'X-Auth-Token'
@auth_token_params ||= ::Widget::TokenService.new(token: request.headers['X-Auth-Token']).decode_token
end
def set_web_widget
@web_widget = ::Channel::WebWidget.find_by!(website_token: permitted_params[:website_token])
@account = @web_widget.account
switch_locale @account
@current_account = @web_widget.account
end
def set_contact
@contact_inbox = @web_widget.inbox.contact_inboxes.find_by(
source_id: auth_token_params[:source_id]
)
@contact = @contact_inbox.contact
@contact = @contact_inbox&.contact
raise ActiveRecord::RecordNotFound unless @contact
end
def create_conversation
::Conversation.create!(conversation_params)
end
def inbox
@inbox ||= ::Inbox.find_by(id: auth_token_params[:inbox_id])
end
def conversation_params
# FIXME: typo referrer in additional attributes, will probably require a migration.
{
account_id: inbox.account_id,
inbox_id: inbox.id,
contact_id: @contact.id,
contact_inbox_id: @contact_inbox.id,
additional_attributes: {
browser: browser_params,
referer: permitted_params[:message][:referer_url],
initiated_at: timestamp_params
}
}
end
def update_contact(email)
contact_with_email = @current_account.contacts.find_by(email: email)
if contact_with_email
@contact = ::ContactMergeAction.new(
account: @current_account,
base_contact: contact_with_email,
mergee_contact: @contact
).perform
else
@contact.update!(email: email, name: contact_name)
end
end
def contact_email
permitted_params[:contact][:email].downcase
end
def contact_name
params[:contact][:name] || contact_email.split('@')[0]
end
def browser_params
{
browser_name: browser.name,
browser_version: browser.full_version,
device_name: browser.device.name,
platform_name: browser.platform.name,
platform_version: browser.platform.version
}
end
def timestamp_params
{ timestamp: permitted_params[:message][:timestamp] }
end
def message_params
{
account_id: conversation.account_id,
sender: @contact,
content: permitted_params[:message][:content],
inbox_id: conversation.inbox_id,
echo_id: permitted_params[:message][:echo_id],
message_type: :incoming
}
end
end
@@ -1,6 +1,7 @@
class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
before_action :set_web_widget
before_action :set_contact
before_action :process_hmac
def show; end
def update
contact_identify_action = ContactIdentifyAction.new(
@@ -12,7 +13,22 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
private
def process_hmac
return if params[:identifier_hash].blank?
raise StandardError, 'HMAC failed: Invalid Identifier Hash Provided' unless valid_hmac?
@contact_inbox.update(hmac_verified: true)
end
def valid_hmac?
params[:identifier_hash] == OpenSSL::HMAC.hexdigest(
'sha256',
@web_widget.hmac_token,
params[:identifier].to_s
)
end
def permitted_params
params.permit(:website_token, :identifier, :email, :name, :avatar_url)
params.permit(:website_token, :identifier, :identifier_hash, :email, :name, :avatar_url, custom_attributes: {})
end
end

Some files were not shown because too many files have changed in this diff Show More