### The problem
Writing in the text editor can be very frustrating, the reason is that
the editor had a debounced save method which would push the article to
the backend and update the current state. This however is a bad idea,
since the can take anywhere between 100-300ms depending on network
conditions.
While this would be in progress, the article is still being edited by
the user. So at the end of the network request, the state returned from
the backend and the current state in the editor is diverged. But since
the update happens anyway, the editor would prepend older context.
```
Time -->
User Action: [Edit 1] ---> [Edit 2] ---> [Edit 3]
Backend Save: Save Req (Edit 1) ----> Response (Edit 1)
Resulting Editor State: [Edit 3] + [Edit 1] (Outdated state prepended)
```
### The solution
The solution is to unbind the article from the backend state, ensuring
that the article editor is the source of truth and ignoring the
responses. This pull request does this by adding an asynchronous save
functionality. The changes include adding a new `saveArticleAsync` event
and ensuring that the local state is not updated unnecessarily during
asynchronous saves.
```
Time -->
User Action: [Edit 1] ---> [Edit 2] ---> [Edit 3]
Backend Save: Save Req (Edit 1) ----> Response (ignored)
Resulting Editor State: [Edit 3] (Consistent and up-to-date)
```
Added the following two debounced methods
These complementary debounce methods prevent unnecessary re-renders
while ensuring backend is in sync. `saveArticleAsync` preserves the
editor as the source of truth, while `saveArticle` manages periodic
state updates from the backend with a delay large enough to safely
assume that the user has stopped typing
Method | Delay | Behavior
-- | -- | --
`saveArticleAsync` | 400ms | Sends data to backend and ignores the
response
`saveArticle` | 2.5s | Sends data and updates local state with the
backend response
### How to test
1. Remove the following line
dc042f6ddc/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticleEditorPage/ArticleEditor.vue (L64)
1. Update the latency here to 400 (P.S. the diff shows the latency to be
600, but that was added as a stop-gap solution)
dc042f6ddc/app/javascript/dashboard/components-next/HelpCenter/Pages/ArticleEditorPage/ArticleEditor.vue (L51)
1. Set the browser network latency to Slow 3G or 3G
1. Start writing on the editor, try fixing typos with backspace or
moving around with the cursor
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
This PR adds dropdown primitives to help compose custom dropdowns across the app. The following the sample usage
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
This PR has the initial version of the new sidebar targeted for the next major redesign of the app. This PR includes the following changes
- Components in the `layouts-next` and `base-next` directories in `dashboard/components`
- Two generic components `Avatar` and `Icon`
- `SidebarGroup` component to manage expandable sidebar groups with nested navigation items. This includes handling active states, transitions, and permissions.
- `SidebarGroupHeader` component to display the header of each navigation group with optional icons and active state indication.
- `SidebarGroupLeaf` component for individual navigation items within a group, supporting icons and active state.
- `SidebarGroupSeparator` component to visually separate nested navigation items. (They look a lot like header)
- `SidebarGroupEmptyLeaf` component to render empty state of any navigation groups.
----
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
Fixes the following issues
- https://chatwoot-p3.sentry.io/issues/5966466083
- https://chatwoot-p3.sentry.io/issues/5966497518
- https://chatwoot-p3.sentry.io/issues/5966555379
For the first one, I am not sure if the fix is 100% correct, since I was
not able to reproduce, but I am confident it will work.
For both, 1st and 2nd issues, the problem came from the fact that we set
individual records to `undefined` when the intent was to remove it,
explicitly using delete fixes the issue.
### Whats up with the store changes?
Glad you asked, this comes down to Vue reactivity, previously Vue didn't
track undefined strictly, it just kinda ignored it, in Vue 3, the
reactivity changed significantly when they introduced ES6 proxies. The
Proxy tracks all property changes, including those set to undefined, so
properties remain enumerable.
So to delete a record, we actually have to the delete it using the
delete keyword, or replace the parent object with a new object splicing
the object to be deleted out.
I am assuming it worked earlier because VueX 3 reactivity was using
Object.defineProperty. Setting it to undefined might have "deleted" it
earlier
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
- Switch to pnpm based build
- Switch circleci from docker to machine to have more memory
- Fix frontend and backend tests
Fixes
https://linear.app/chatwoot/issue/CW-3610/fix-circle-ci-for-vite-build
---------
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
This PR fixes the issue where proper error messages from the backend
were not displayed when an email already exists in the system during a
profile update, or when a phone number is already taken for Twilio
during the creation of a new account.
Fixes:
https://linear.app/chatwoot/issue/CW-3560/prod-customer-facing-issue-updating-email
In admin settings, this Pr will add the UI for managing custom roles (
ref: https://github.com/chatwoot/chatwoot/pull/9995 ). It also handles
the routing logic changes to accommodate fine-tuned permissions.
---------
Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This is the continuation of the design update for the settings screens.
In this PR, the automation page is updated with the latest design.
- Moved the row to a new component
- Migrated both components to composition API.
- Order by ID (Earlier this was order by updated_at which was
confusing).
| Light | Dark |
| -- | -- |
| <img width="1438" alt="Screenshot 2024-08-21 at 9 46 48 PM"
src="https://github.com/user-attachments/assets/89d96745-6556-48a1-82fa-a115325c24c0">
| <img width="1398" alt="Screenshot 2024-08-21 at 9 46 57 PM"
src="https://github.com/user-attachments/assets/5f1935ec-6d0e-4f82-b895-f47244764474">
|
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
This is the continuation of the design update series. Canned responses listing page is rewritten with the design change.
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Fix the broken message sending due to the errors in attachment update PR
https://github.com/chatwoot/chatwoot/pull/9784
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
When the chat is viewed, a function `fetchAllAttachments` is run to get all attachments for a particular conversation. This function, before updating the record creates the `attachments` property on the `chat` object in the store.
If in any case this function fails, the `attachments` property is not created, and when the code reaches the `dashboard/store/modules/conversations/index.js` the error occurs
This PR fixes it by ensuring that `SET_ALL_ATTACHMENTS` is always run. And it handles the default case as well
---
Sentry Issue:
[CHATWOOT-FRONTEND-APP-5Y](https://chatwoot-p3.sentry.io/issues/5459056982/)
```
TypeError: Cannot read properties of undefined (reading 'some')
at forEach(./app/javascript/dashboard/store/modules/conversations/index.js:160:31)
at Array.forEach(<anonymous>)
at mutations(./app/javascript/dashboard/store/modules/conversations/index.js:159:27)
at handler(./node_modules/vuex/dist/vuex.js:771:7)
at forEach(./node_modules/vuex/dist/vuex.js:470:9)
at Array.forEach(<anonymous>)
at fn(./node_modules/vuex/dist/vuex.js:469:13)
at Store.prototype._withCommit(./node_modules/vuex/dist/vuex.js:574:5)
at Store.prototype.commit(./node_modules/vuex/dist/vuex.js:468:10)
at this.commit(./node_modules/vuex/dist/vuex.js:420:21)
at call(./app/javascript/dashboard/store/modules/conversations/actions.js:273:7)
at tryCatch(./node_modules/videojs-record/dist/videojs.record.js:2868:27)
at _invoke(./node_modules/videojs-record/dist/videojs.record.js:3088:32)
at prototype[method](./node_modules/videojs-record/dist/videojs.record.js:2921:31)
at as(/packs/js/application-cf716bca3c984faeb095.js:4:76)
at as(/packs/js/application-cf716bca3c984faeb095.js:4:76)
at nrWrapper(/app/accounts/81898/conversations/95:6:17817)
```
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Combine integrations and applications page into one page.
<img width="1182" alt="Screenshot 2024-07-23 at 3 30 51 PM"
src="https://github.com/user-attachments/assets/50920a6f-606f-44b3-b1e4-641046a14444">
Major changes:
- The app enabled?, active? checks are all moved to backend.
- The dashboard_apps integration is also now part of the apps.yml file.
- Updated the header design for the new settings pages.
- Merged the folders integrationapps and integrations.
- Updated the copy to match the size of the card and provide clear
instruction.
- Only the list page is updated in this PR, rest of the pages are yet to
be migrated.
| Integration | Verified |
| -- | -- |
| Dashboard Apps | ✅ |
| Dyte | ✅ |
| Slack | ✅ |
| Webhooks | ✅ |
| Dialogflow | ✅ |
| Google Translate | ✅ |
| OpenAI | ✅ |
| Linear | ✅ |
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Due to the pattern `**/specs/*.spec.js` defined in CircleCI, none of the
frontend spec in the folders such as
`specs/<domain-name>/getters.spec.js` were not executed in Circle CI.
This PR fixes the issue, along with the following changes:
- Use vitest instead of jest
- Remove jest dependancies
- Update tests to work with vitest
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
# Replace the deprecated `eventBus` with mitt.js
## Description
Since eventBus and it's respective methods are deprecated and removed
from all future releases of vue, this was blocking us from migrating.
This PR replaces eventBus with
[mitt](https://github.com/developit/mitt). I have created a wrapper
mitt.js to simulate the same old event names so it's backwards
compatible, without making a lot of changes.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
1. Made sure all the places we're listening to bus events are working as
expected.
2. Respective specsf or the events from mitt.
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
- Add an upgrade CTA for the SLA feature
-------------------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Updating the `unattended` tab to include conversations where the customer responded and is awaiting an agent's response.
Previously it showed only the conversations where the first response was pending.
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
* feat: Attachments view with key shortcuts and dynamically updates when user delete or sent new attachments
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
* fix: Search improvements and bug fixes
* Resets tab to all on search
* Fix index bug with tabs
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
* feat: init auditlogs ui
* chore: add api
* fix: action
* chore: add action,username,time
* feat: add pagination support
* chore: format time
* chore: refactor
* chore: refactor auditlogs api response
* chore: update icon
* chore: rubocop fixes
* Fixes the way meta is handled in store
* Fixes meta not appearing issue
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
* feat: sort by position
* chore: whitespace change
* feat: add border bottom color to list item
* feat: allow dragging articles
* feat: add migration to reorder all articles
* feat: add onsort method
* feat: finish UI sorting
* feat: show 50 per page in articles list
* feat: add article sorting methods
* feat: patch up reorder action with the API
* refactor: better naming
* chore: add comments
* feat: attach position to article before create
* feat: move article to end if moved between categories
* chore: add comments
* chore: update version
* fix: don't change position if previous category was nil
* fix: condition to trigger update on category change
* refactor: store new_position
* refactor: use grid instead of table
* feat: add snug spacing
* feat: add grab-icon
* feat: add grab icon to list
* refactor: show draggable only for category page
* feat: add update_positions as a class method
---------
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
* feat: genearte report in a grid
* refactor: update API usage
* refactor: separate generate method
* refactor: abstract transform_data
* feat: annotate with comments
* feat: add explicit timezone
* feat: download data only in user timezone
* fix: dates included in heatmap
* feat: add heatmap component
* feat: add heatmap component
* feat: add dummy heatmap
* refactor: compact tiles
* feat: allow hour
* feat: wire up heatmap query
* feat: allow arbritrary number of weeks
* feat: update position of the widget
* chore: update heatmap title
* refactor: move traffic heatmap to overview
* chore: add comment for perf
* feat: add reconcile logic for heatmap fetching
Fetching the data for the last 6 days all the time is wasteful
So we fetch only the data for today and reconcile it with the data we already have
* refactor: re-org code for new utils
* feat: add translations
* feat: translate days of the week
* chore: update chatwoot utils
* feat: add markers to heatmap
* refactor: update class names
* refactor: move flatten as a separate method
* test: Heatmap Helpers
* chore: add comments
* refactor: method naming
* refactor: use heatmap-level mixin
* refactor: cleanup css
* chore: remove log
* refactor: reports.js to use object instead of separate params
* refactor: report store to use new API design
* refactor: rename HeatmapHelper -> ReportsDataHelper
* refactor: separate clampDataBetweenTimeline
* feat: add tests
* fix: group by hour
* feat: add scroll for smaller screens
* refactor: add base data to reconcile with
* fix: tests
* fix: overflow only on smaller screens
* feat: translate tooltip
* refactor: simplify reconcile
* chore: add docs
* chore: remoev heatmap from account report
* feat: let Heatmap handle loading state
* chore: Apply suggestions from code review
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
* feat: update css
* refactor: color assignment to range
* feat: add short circuit
* Update app/javascript/dashboard/routes/dashboard/settings/reports/components/Heatmap.vue
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
* Added one more endpoint to attach tempfile and get logo
* Added one more endpoint to attach tempfile and get logo
* spec fixes
* Upload file for articles irrespective of the association
* Upload file for articles irrespective of the association
* Add multiple images with different keys
* feat: Adds image attachment for help center articles
* Adds validation for file upload
* Fixes space above image after adding to doc
* chore: Removed svg from file upload type
* Update app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
* Update app/javascript/dashboard/components/widgets/WootWriter/FullEditor.vue
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
* Removes caption for the image
* Fixes woot prosemirror package version
* Update yarn.lock
* Update yarn.lock
---------
Co-authored-by: Tejaswini Chile <tejaswini@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
* fix: Update unread_count from backend instead of computing on the frontend
* Fix spec
* Remove status indicator on private notifications
* CodeClimate fix
* CodeClimate
- Add more feature flags for CRM, auto_resolution, and reports
- Add a SuperAdmin link in the sidebar if the user is a super-admin
- SuperAdmin could view all the features on an account irrespective of whether the feature is enabled.
Adds the ability to lock conversation to a single thread for Whatsapp and Sms Inboxes when using outbound messages.
demo: https://www.loom.com/share/c9e1e563c8914837a4139dfdd2503feffixes: #4975
Co-authored-by: Nithin David <1277421+nithindavid@users.noreply.github.com>
* feat: Adds the ability to publish an article
* chore: Disabled publish button and dropdown when there is no article id
* chore: Review fixes
* chore: Review fixes
* Update app/javascript/dashboard/routes/dashboard/helpcenter/components/Header/EditArticleHeader.vue
* chore: Review fixes
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>