chore: Save company list sorting preferences in UI settings (#12916)

# Pull Request Template

## Description

This PR saves the company list sorting preferences (field and order) in
the user’s UI settings. The sort state is initialized from the stored
preferences when the component mounts, defaulting to `-created_at` if
none exist.

Fixes
https://linear.app/chatwoot/issue/CW-5992/save-sort-filter-to-ui-settings

## Type of change
- [x] New feature (non-breaking change which adds functionality)


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] 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
- [ ] Any dependent changes have been merged and published in downstream
modules
This commit is contained in:
Sivin Varghese
2025-11-21 06:21:27 +05:30
committed by GitHub
parent a547c28c8d
commit 38d6ee6dd2

View File

@@ -1,14 +1,16 @@
<script setup> <script setup>
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted, reactive } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useMapGetter } from 'dashboard/composables/store'; import { useMapGetter } from 'dashboard/composables/store';
import { useUISettings } from 'dashboard/composables/useUISettings';
import { debounce } from '@chatwoot/utils'; import { debounce } from '@chatwoot/utils';
import CompaniesListLayout from 'dashboard/components-next/Companies/CompaniesListLayout.vue'; import CompaniesListLayout from 'dashboard/components-next/Companies/CompaniesListLayout.vue';
import CompaniesCard from 'dashboard/components-next/Companies/CompaniesCard/CompaniesCard.vue'; import CompaniesCard from 'dashboard/components-next/Companies/CompaniesCard/CompaniesCard.vue';
const DEFAULT_SORT_FIELD = 'created_at';
const DEBOUNCE_DELAY = 300; const DEBOUNCE_DELAY = 300;
const store = useStore(); const store = useStore();
@@ -16,19 +18,33 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const { updateUISettings, uiSettings } = useUISettings();
const searchQuery = computed(() => route.query?.search || ''); const searchQuery = computed(() => route.query?.search || '');
const searchValue = ref(searchQuery.value); const searchValue = ref(searchQuery.value);
const pageNumber = computed(() => Number(route.query?.page) || 1); const pageNumber = computed(() => Number(route.query?.page) || 1);
const activeSort = computed(() => { const parseSortSettings = (sortString = '') => {
const sortParam = route.query?.sort || 'name'; const hasDescending = sortString.startsWith('-');
return sortParam.startsWith('-') ? sortParam.slice(1) : sortParam; const sortField = hasDescending ? sortString.slice(1) : sortString;
return {
sort: sortField || DEFAULT_SORT_FIELD,
order: hasDescending ? '-' : '',
};
};
const { companies_sort_by: companySortBy = `-${DEFAULT_SORT_FIELD}` } =
uiSettings.value ?? {};
const { sort: initialSort, order: initialOrder } =
parseSortSettings(companySortBy);
const sortState = reactive({
activeSort: initialSort,
activeOrdering: initialOrder,
}); });
const activeOrdering = computed(() => { const activeSort = computed(() => sortState.activeSort);
const sortParam = route.query?.sort || 'name'; const activeOrdering = computed(() => sortState.activeOrdering);
return sortParam.startsWith('-') ? '-' : '';
});
const companies = useMapGetter('companies/getCompaniesList'); const companies = useMapGetter('companies/getCompaniesList');
const meta = useMapGetter('companies/getMeta'); const meta = useMapGetter('companies/getMeta');
@@ -36,11 +52,10 @@ const uiFlags = useMapGetter('companies/getUIFlags');
const isFetchingList = computed(() => uiFlags.value.fetchingList); const isFetchingList = computed(() => uiFlags.value.fetchingList);
const sortParam = computed(() => { const buildSortAttr = () =>
return activeOrdering.value === '-' `${sortState.activeOrdering}${sortState.activeSort}`;
? `-${activeSort.value}`
: activeSort.value; const sortParam = computed(() => buildSortAttr());
});
const updateURLParams = (page, search = '', sort = '') => { const updateURLParams = (page, search = '', sort = '') => {
const query = { const query = {
@@ -96,9 +111,14 @@ const onPageChange = page => {
fetchCompanies(page, searchValue.value, sortParam.value); fetchCompanies(page, searchValue.value, sortParam.value);
}; };
const handleSort = ({ sort, order }) => { const handleSort = async ({ sort, order }) => {
const newSortParam = order === '-' ? `-${sort}` : sort; Object.assign(sortState, { activeSort: sort, activeOrdering: order });
fetchCompanies(1, searchValue.value, newSortParam);
await updateUISettings({
companies_sort_by: buildSortAttr(),
});
fetchCompanies(1, searchValue.value, buildSortAttr());
}; };
onMounted(() => { onMounted(() => {