Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
03a18d3
chore: added empty row between the fields to improve readability
aleksandernsilva Feb 28, 2025
1a9bbda
refactor: moved department payload formatting to util
aleksandernsilva Feb 28, 2025
f5b29af
refactor: moved agent list payload formatting to util
aleksandernsilva Feb 28, 2025
88745ac
refactor: moved getFormInitialValues to util
aleksandernsilva Feb 28, 2025
7e0c545
refactor: moved type definitions to its own file
aleksandernsilva Feb 28, 2025
a9ab5ca
refactor: rename util from formatDepartmentPayload to formatEditDepar…
aleksandernsilva Feb 28, 2025
db1bc5b
feat: added unit field to edit department page
aleksandernsilva Feb 28, 2025
fe91484
refactor: changed empty option to none
aleksandernsilva Mar 5, 2025
36c5352
refactor: use rest endpoints instead of meteor methods
aleksandernsilva Mar 5, 2025
2d42aa0
refactor: use LivechatDepartmentDTO
aleksandernsilva Mar 5, 2025
9ac763b
chore: updated types
aleksandernsilva Mar 5, 2025
5cd676d
chore: changeset
aleksandernsilva Mar 6, 2025
7180c39
test: added e2e tests
aleksandernsilva Mar 6, 2025
0ed1d3c
refactor: reverted to requestTagsBeforeClosingChat
aleksandernsilva Mar 10, 2025
583e34b
refactor: code style & add new agent check
aleksandernsilva Mar 10, 2025
d55cec0
feat: disable unit field when editing a department
aleksandernsilva Mar 17, 2025
50010fe
test: added test case for disabled unit field when editing
aleksandernsilva Mar 17, 2025
a5c2d83
refactor: changed var names
aleksandernsilva Mar 18, 2025
0f59d8d
feat: added event onLoadItems to AutoCompleteUnit
aleksandernsilva Mar 18, 2025
d64832b
feat: allow editing unit only if not already set
aleksandernsilva Mar 18, 2025
7581581
feat: consider unit field required if user has units assigned
aleksandernsilva Mar 18, 2025
aeeb82d
refactor: consider none option in the itemCount
aleksandernsilva Mar 19, 2025
082a372
Merge branch 'develop' into feat/department-unit
kodiakhq[bot] Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/large-islands-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@rocket.chat/model-typings': minor
'@rocket.chat/core-typings': minor
'@rocket.chat/rest-typings': minor
'@rocket.chat/models': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Adds a new "Unit" field to the create/edit department page, allowing users to specify a business unit when creating or editing a department.
17 changes: 14 additions & 3 deletions apps/meteor/client/components/Omnichannel/hooks/useUnitsList.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { useScrollableRecordList } from '../../../hooks/lists/useScrollableRecordList';
import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate';
import { RecordList } from '../../../lib/lists/RecordList';

type UnitsListOptions = {
text: string;
haveNone?: boolean;
};

type UnitOption = { value: string; label: string; _id: string };
export type UnitOption = { value: string; label: string; _id: string };

export const useUnitsList = (
options: UnitsListOptions,
Expand All @@ -19,6 +21,8 @@ export const useUnitsList = (
reload: () => void;
loadMoreItems: (start: number, end: number) => void;
} => {
const { t } = useTranslation();
const { haveNone = false } = options;
const [itemsList, setItemsList] = useState(() => new RecordList<UnitOption>());
const reload = useCallback(() => setItemsList(new RecordList<UnitOption>()), []);

Expand All @@ -44,12 +48,19 @@ export const useUnitsList = (
value: u._id,
}));

haveNone &&
items.unshift({
_id: '',
label: t('None'),
value: '',
});

return {
items,
itemCount: total,
itemCount: haveNone ? total + 1 : total,
};
},
[getUnits, text],
[getUnits, haveNone, t, text],
);

const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { PaginatedSelectFiltered } from '@rocket.chat/fuselage';
import { useDebouncedValue, useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';

import type { UnitOption } from '../../components/Omnichannel/hooks/useUnitsList';
import { useUnitsList } from '../../components/Omnichannel/hooks/useUnitsList';
import { useRecordList } from '../../hooks/lists/useRecordList';
import { AsyncStatePhase } from '../../lib/asyncState';
import type { RecordList } from '../../lib/lists/RecordList';

type AutoCompleteUnitProps = {
disabled?: boolean;
value: string | undefined;
error?: string;
placeholder?: string;
haveNone?: boolean;
onChange: (value: string) => void;
onLoadItems?: (list: RecordList<UnitOption>) => void;
};

const AutoCompleteUnit = ({
value,
disabled = false,
error,
placeholder,
haveNone,
onChange,
onLoadItems = () => undefined,
}: AutoCompleteUnitProps) => {
const { t } = useTranslation();
const [unitsFilter, setUnitsFilter] = useState<string>('');

const debouncedUnitFilter = useDebouncedValue(unitsFilter, 500);

const { itemsList, loadMoreItems: loadMoreUnits } = useUnitsList(
useMemo(() => ({ text: debouncedUnitFilter, haveNone }), [debouncedUnitFilter, haveNone]),
);
const { phase: unitsPhase, itemCount: unitsTotal, items: unitsList } = useRecordList(itemsList);

const handleLoadItems = useEffectEvent(onLoadItems);

useEffect(() => {
handleLoadItems(itemsList);
}, [handleLoadItems, unitsTotal, itemsList]);

return (
<PaginatedSelectFiltered
data-qa='autocomplete-unit'
error={error}
filter={unitsFilter}
flexGrow={0}
flexShrink={0}
disabled={disabled}
onChange={onChange}
options={unitsList}
placeholder={placeholder || t('Select_an_option')}
setFilter={setUnitsFilter as (value: string | number | undefined) => void}
value={value}
width='100%'
endReached={
unitsPhase === AsyncStatePhase.LOADING ? (): void => undefined : (start): void => loadMoreUnits(start, Math.min(50, unitsTotal))
}
/>
);
};

export default AutoCompleteUnit;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';

import AutoCompleteAgent from '../../../../components/AutoCompleteAgent';
import { useEndpointAction } from '../../../../hooks/useEndpointAction';
import type { IDepartmentAgent } from '../EditDepartment';
import type { IDepartmentAgent } from '../definitions';

function AddAgent({ agentList, onAdd }: { agentList: IDepartmentAgent[]; onAdd: (agent: IDepartmentAgent) => void }) {
const { t } = useTranslation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import type { UseFormRegister } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable';
import type { FormValues, IDepartmentAgent } from '../EditDepartment';
import type { EditDepartmentFormData, IDepartmentAgent } from '../definitions';
import AgentAvatar from './AgentAvatar';
import RemoveAgentButton from './RemoveAgentButton';

type AgentRowProps = {
agent: IDepartmentAgent;
index: number;
register: UseFormRegister<FormValues>;
register: UseFormRegister<EditDepartmentFormData>;
onRemove: (agentId: string) => void;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { useTranslation } from 'react-i18next';

import { GenericTable, GenericTableBody, GenericTableHeader, GenericTableHeaderCell } from '../../../../components/GenericTable';
import { usePagination } from '../../../../components/GenericTable/hooks/usePagination';
import type { FormValues } from '../EditDepartment';
import type { EditDepartmentFormData } from '../definitions';
import AddAgent from './AddAgent';
import AgentRow from './AgentRow';

type DepartmentAgentsTableProps = {
control: Control<FormValues>;
register: UseFormRegister<FormValues>;
control: Control<EditDepartmentFormData>;
register: UseFormRegister<EditDepartmentFormData>;
};

function DepartmentAgentsTable({ control, register }: DepartmentAgentsTableProps) {
Expand Down
Loading
Loading