Skip to content

Commit

Permalink
[NEW] Paginated and Filtered selects on new/edit unit (#22052)
Browse files Browse the repository at this point in the history
* create endpoint to show departments not related with unit

* department refactor endpoint by unit and available by unit

* [NEW] Paginated and Filtered selects on new/edit unit

* TS fixes

Typescript pls don't hurt me

* More TS fixes

Co-authored-by: Rafael <rafaelblink@gmail.com>
  • Loading branch information
2 people authored and sampaiodiego committed May 19, 2021
1 parent d1062ef commit fdb6639
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 78 deletions.
6 changes: 6 additions & 0 deletions client/contexts/ServerContext/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { ListEndpoint as EmojiCustomListEndpoint } from './endpoints/v1/emoji-cu
import { FilesEndpoint as GroupsFilesEndpoint } from './endpoints/v1/groups/files';
import { FilesEndpoint as ImFilesEndpoint } from './endpoints/v1/im/files';
import { AppearanceEndpoint as LivechatAppearanceEndpoint } from './endpoints/v1/livechat/appearance';
import { LivechatDepartment } from './endpoints/v1/livechat/department';
import { LivechatDepartmentsByUnit } from './endpoints/v1/livechat/departmentsByUnit';
import { LivechatMonitorsList } from './endpoints/v1/livechat/monitorsList';
import { LivechatRoomOnHoldEndpoint } from './endpoints/v1/livechat/onHold';
import { LivechatVisitorInfoEndpoint } from './endpoints/v1/livechat/visitorInfo';
import { AutocompleteAvailableForTeamsEndpoint as RoomsAutocompleteTeamsEndpoint } from './endpoints/v1/rooms/autocompleteAvailableForTeams';
Expand Down Expand Up @@ -40,6 +43,9 @@ export type ServerEndpoints = {
'teams.addRooms': TeamsAddRoomsEndpoint;
'livechat/visitors.info': LivechatVisitorInfoEndpoint;
'livechat/room.onHold': LivechatRoomOnHoldEndpoint;
'livechat/monitors.list': LivechatMonitorsList;
'livechat/department': LivechatDepartment;
'livechat/departments.by-unit/': LivechatDepartmentsByUnit;
};

export type ServerEndpointPath = keyof ServerEndpoints;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type LivechatDepartment = {
GET: (params: {
query: string;
}) => {
statuses: unknown[];
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment';
import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi';

export type LivechatDepartmentsByUnit = {
GET: (params: {
text: string;
offset: number;
count: number;
}) => {
departments: ObjectFromApi<ILivechatDepartment>[];
total: number;
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ILivechatMonitor } from '../../../../../../definition/ILivechatMonitor';
import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi';

export type LivechatMonitorsList = {
GET: (params: {
text: string;
offset: number;
count: number;
}) => {
monitors: ObjectFromApi<ILivechatMonitor>[];
total: number;
};
};
63 changes: 63 additions & 0 deletions client/views/hooks/useDepartmentsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useCallback, useState } from 'react';

import { ILivechatDepartmentRecord } from '../../../definition/ILivechatDepartmentRecord';
import { useEndpoint } from '../../contexts/ServerContext';
import { useScrollableRecordList } from '../../hooks/lists/useScrollableRecordList';
import { useComponentDidUpdate } from '../../hooks/useComponentDidUpdate';
import { RecordList } from '../../lib/lists/RecordList';

type DepartmentsListOptions = {
unitId: string;
filter: string;
};

export const useDepartmentsList = (
options: DepartmentsListOptions,
): {
itemsList: RecordList<ILivechatDepartmentRecord>;
initialItemCount: number;
reload: () => void;
loadMoreItems: (start: number, end: number) => void;
} => {
const [itemsList, setItemsList] = useState(() => new RecordList<ILivechatDepartmentRecord>());
const reload = useCallback(() => setItemsList(new RecordList<ILivechatDepartmentRecord>()), []);
const endpoint = `livechat/departments.available-by-unit/${
options.unitId || 'none'
}` as 'livechat/departments.by-unit/';

const getDepartments = useEndpoint('GET', endpoint);

useComponentDidUpdate(() => {
options && reload();
}, [options, reload]);

const fetchData = useCallback(
async (start, end) => {
const { departments, total } = await getDepartments({
text: options.filter,
offset: start,
count: end + start,
});

return {
items: departments.map((department: any) => {
department._updatedAt = new Date(department._updatedAt);
department.label = department.name;
department.value = { value: department._id, label: department.name };
return department;
}),
itemCount: total,
};
},
[getDepartments, options.filter],
);

const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25);

return {
reload,
itemsList,
loadMoreItems,
initialItemCount,
};
};
60 changes: 60 additions & 0 deletions client/views/hooks/useMonitorsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useCallback, useState } from 'react';

import { ILivechatMonitorRecord } from '../../../definition/ILivechatMonitorRecord';
import { useEndpoint } from '../../contexts/ServerContext';
import { useScrollableRecordList } from '../../hooks/lists/useScrollableRecordList';
import { useComponentDidUpdate } from '../../hooks/useComponentDidUpdate';
import { RecordList } from '../../lib/lists/RecordList';

type MonitorsListOptions = {
filter: string;
};

export const useMonitorsList = (
options: MonitorsListOptions,
): {
itemsList: RecordList<ILivechatMonitorRecord>;
initialItemCount: number;
reload: () => void;
loadMoreItems: (start: number, end: number) => void;
} => {
const [itemsList, setItemsList] = useState(() => new RecordList<ILivechatMonitorRecord>());
const reload = useCallback(() => setItemsList(new RecordList<ILivechatMonitorRecord>()), []);

const endpoint = 'livechat/monitors.list';

const getMonitors = useEndpoint('GET', endpoint);

useComponentDidUpdate(() => {
options && reload();
}, [options, reload]);

const fetchData = useCallback(
async (start, end) => {
const { monitors, total } = await getMonitors({
text: options.filter,
offset: start,
count: end + start,
});

return {
items: monitors.map((members: any) => {
members._updatedAt = new Date(members._updatedAt);
members.label = members.username;
members.value = { value: members._id, label: members.username };
return members;
}),
itemCount: total,
};
},
[getMonitors, options.filter],
);

const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25);
return {
reload,
itemsList,
loadMoreItems,
initialItemCount,
};
};
17 changes: 17 additions & 0 deletions definition/ILivechatDepartmentRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { IRocketChatRecord } from './IRocketChatRecord';


export interface ILivechatDepartmentRecord extends IRocketChatRecord {
_id: string;
name: string;
enabled: boolean;
description: string;
showOnRegistration: boolean;
showOnOfflineForm: boolean;
requestTagBeforeClosingChat: boolean;
email: string;
chatClosingTags: string[];
offlineMessageChannelName: string;
numAgents: number;
businessHourId?: string;
}
8 changes: 8 additions & 0 deletions definition/ILivechatMonitor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface ILivechatMonitor {
_id: string;
name: string;
enabled: boolean;
numMonitors: number;
type: string;
visibility: string;
}
11 changes: 11 additions & 0 deletions definition/ILivechatMonitorRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IRocketChatRecord } from './IRocketChatRecord';


export interface ILivechatMonitorRecord extends IRocketChatRecord {
_id: string;
name: string;
enabled: boolean;
numMonitors: number;
type: string;
visibility: string;
}
44 changes: 44 additions & 0 deletions ee/app/livechat-enterprise/server/api/departments.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {
findPercentageOfAbandonedRooms,
findAllAverageOfChatDurationTime,
} from '../../../../../app/livechat/server/lib/analytics/departments';
import {
findAllDepartmentsAvailable,
findAllDepartmentsByUnit,
} from '../lib/Department';

API.v1.addRoute('livechat/analytics/departments/amount-of-chats', { authRequired: true }, {
get() {
Expand Down Expand Up @@ -318,3 +322,43 @@ API.v1.addRoute('livechat/analytics/departments/percentage-abandoned-chats', { a
});
},
});

API.v1.addRoute('livechat/departments.available-by-unit/:unitId', { authRequired: true }, {
get() {
check(this.urlParams, {
unitId: Match.Maybe(String),
});
const { offset, count } = this.getPaginationItems();
const { unitId } = this.urlParams;
const { text } = this.queryParams;


const { departments, total } = Promise.await(findAllDepartmentsAvailable(unitId, offset, count, text));

return API.v1.success({
departments,
count: departments.length,
offset,
total,
});
},
});

API.v1.addRoute('livechat/departments.by-unit/:unitId', { authRequired: true }, {
get() {
check(this.urlParams, {
unitId: String,
});
const { offset, count } = this.getPaginationItems();
const { unitId } = this.urlParams;

const { departments, total } = Promise.await(findAllDepartmentsByUnit(unitId, offset, count));

return API.v1.success({
departments,
count: departments.length,
offset,
total,
});
},
});
32 changes: 32 additions & 0 deletions ee/app/livechat-enterprise/server/lib/Department.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { escapeRegExp } from '@rocket.chat/string-helpers';

import {
LivechatDepartment,
} from '../../../../../app/models/server/raw';

export const findAllDepartmentsAvailable = async (unitId, offset, count, text) => {
const filterReg = new RegExp(escapeRegExp(text), 'i');

const cursor = LivechatDepartment.find({
$or: [{ ancestors: { $in: [unitId] } }, { ancestors: { $exists: false } }],
...text && { name: filterReg },

}, { limit: count, offset });

const departments = await cursor.toArray();
const total = await cursor.count();
const departmentsFiltered = departments.filter((department) => !department.ancestors?.length);

return { departments: departmentsFiltered, total };
};

export const findAllDepartmentsByUnit = async (unitId, offset, count) => {
const cursor = LivechatDepartment.find({
ancestors: { $in: [unitId] },
}, { limit: count, offset });

const total = await cursor.count();
const departments = await cursor.toArray();

return { departments, total };
};
Loading

0 comments on commit fdb6639

Please sign in to comment.