Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ const AgentRow = ({ index, agent, register, onRemove }: AgentRowProps) => {
<AgentAvatar name={agent.name || ''} username={agent.username || ''} />
</GenericTableCell>
<GenericTableCell fontScale='p2' color='hint' withTruncatedText>
<NumberInput title={t('Count')} maxWidth='100%' {...register(`agentList.${index}.count`, { valueAsNumber: true })} />
<NumberInput title={t('Count')} maxWidth='100%' {...register(`agentList.${index}.count`, { valueAsNumber: true, min: 0 })} />
</GenericTableCell>
<GenericTableCell fontScale='p2' color='hint' withTruncatedText>
<NumberInput title={t('Order')} maxWidth='100%' {...register(`agentList.${index}.order`, { valueAsNumber: true })} />
<NumberInput title={t('Order')} maxWidth='100%' {...register(`agentList.${index}.order`, { valueAsNumber: true, min: 0 })} />
</GenericTableCell>
<GenericTableCell fontScale='p2' color='hint'>
<RemoveAgentButton agentId={agent.agentId} onRemove={onRemove} />
</GenericTableCell>
</GenericTableRow>
);
};

export default memo(AgentRow);
45 changes: 45 additions & 0 deletions apps/meteor/tests/end-to-end/api/livechat/10-departments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@ import { IS_EE } from '../../../e2e/config/constants';
.expect(200);
expect(res.body).to.have.property('success', true);
});

it('should successfully remove an agent from a department', async () => {
const [dep, agent] = await Promise.all([createDepartment(), createAgent()]);
const res = await request
Expand All @@ -940,6 +941,50 @@ import { IS_EE } from '../../../e2e/config/constants';
expect(res.body).to.have.property('success', true);
await deleteDepartment(dep._id);
});

describe('count and order validation', () => {
let dep: ILivechatDepartment;
let agent: IUser;

before(async () => {
await updatePermission('manage-livechat-departments', ['admin']);
await updatePermission('add-livechat-department-agents', ['admin', 'livechat-manager']);
[dep, agent] = await Promise.all([createDepartment(), createAgent()]);
});

after(async () => {
await deleteDepartment(dep._id);
});

it('should fail if count is negative', async () => {
const res = await request
.post(api(`livechat/department/${dep._id}/agents`))
.set(credentials)
.send({ upsert: [{ agentId: agent._id, username: agent.username, count: -1, order: 0 }], remove: [] })
.expect(400);
expect(res.body).to.have.property('success', false);
expect(res.body.error).to.include('must be >= 0');
});

it('should fail if order is negative', async () => {
const res = await request
.post(api(`livechat/department/${dep._id}/agents`))
.set(credentials)
.send({ upsert: [{ agentId: agent._id, username: agent.username, count: 0, order: -1 }], remove: [] })
.expect(400);
expect(res.body).to.have.property('success', false);
expect(res.body.error).to.include('must be >= 0');
});

it('should successfully add an agent when count and order are 0', async () => {
const res = await request
.post(api(`livechat/department/${dep._id}/agents`))
.set(credentials)
.send({ upsert: [{ agentId: agent._id, username: agent.username, count: 0, order: 0 }], remove: [] })
.expect(200);
expect(res.body).to.have.property('success', true);
});
});
});

describe('Department archivation', () => {
Expand Down
6 changes: 6 additions & 0 deletions packages/rest-typings/src/v1/omnichannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ const LivechatDepartmentDepartmentIdAgentsPOSTSchema = {
name: { type: 'string' },
count: {
type: 'number',
minimum: 0,
},
order: {
type: 'number',
minimum: 0,
},
},
required: ['agentId', 'username'],
Expand All @@ -211,9 +213,11 @@ const LivechatDepartmentDepartmentIdAgentsPOSTSchema = {
},
count: {
type: 'number',
minimum: 0,
},
order: {
type: 'number',
minimum: 0,
},
departmentEnabled: { type: 'boolean' },
departmentId: { type: 'string' },
Expand Down Expand Up @@ -826,10 +830,12 @@ const POSTLivechatDepartmentSchema = {
},
count: {
type: 'number',
minimum: 0,
nullable: true,
},
order: {
type: 'number',
minimum: 0,
nullable: true,
},
},
Expand Down