Chore: Migrate ee/omnichannel folder to Typescript (#3749)
* Chore: Migrate ee/omnichannel folder to Typescript * omnichannelstatus and queue list * boolean searching and react.ref * test initi * test and refactor interfaces * minor tweak * minor tweaks
This commit is contained in:
parent
091055a255
commit
b7e523a267
|
@ -4,7 +4,7 @@ import { MarkdownAST } from '@rocket.chat/message-parser';
|
|||
import { IAttachment } from './IAttachment';
|
||||
import { IMessage } from './IMessage';
|
||||
import { IServedBy } from './IServedBy';
|
||||
import { SubscriptionType } from './ISubscription';
|
||||
import { IVisitor, SubscriptionType } from './ISubscription';
|
||||
import { IUser } from './IUser';
|
||||
|
||||
interface IRequestTranscript {
|
||||
|
@ -28,11 +28,8 @@ export interface IRoom {
|
|||
broadcast: boolean;
|
||||
encrypted: boolean;
|
||||
ro: boolean;
|
||||
v?: {
|
||||
_id?: string;
|
||||
token?: string;
|
||||
status: 'online' | 'busy' | 'away' | 'offline';
|
||||
};
|
||||
v?: IVisitor;
|
||||
status?: string;
|
||||
servedBy?: IServedBy;
|
||||
departmentId?: string;
|
||||
livechatData?: any;
|
||||
|
@ -55,13 +52,11 @@ export enum OmnichannelSourceType {
|
|||
API = 'api',
|
||||
OTHER = 'other' // catch-all source type
|
||||
}
|
||||
export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | 'broadcast' | ''> {
|
||||
export interface IOmnichannelRoom extends Partial<Omit<IRoom, 'default' | 'featured' | 'broadcast'>> {
|
||||
_id: string;
|
||||
rid: string;
|
||||
t: SubscriptionType.OMNICHANNEL;
|
||||
v: {
|
||||
_id?: string;
|
||||
token?: string;
|
||||
status: 'online' | 'busy' | 'away' | 'offline';
|
||||
};
|
||||
v: IVisitor;
|
||||
email?: {
|
||||
// Data used when the room is created from an email, via email Integration.
|
||||
inbox: string;
|
||||
|
@ -83,6 +78,8 @@ export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | '
|
|||
sidebarIcon?: string;
|
||||
// The default sidebar icon
|
||||
defaultIcon?: string;
|
||||
_updatedAt?: Date;
|
||||
queuedAt?: Date;
|
||||
};
|
||||
transcriptRequest?: IRequestTranscript;
|
||||
servedBy?: IServedBy;
|
||||
|
@ -91,18 +88,22 @@ export interface IOmnichannelRoom extends Omit<IRoom, 'default' | 'featured' | '
|
|||
|
||||
lastMessage?: IMessage & { token?: string };
|
||||
|
||||
tags: any;
|
||||
closedAt: any;
|
||||
metrics: any;
|
||||
waitingResponse: any;
|
||||
responseBy: any;
|
||||
priorityId: any;
|
||||
livechatData: any;
|
||||
tags?: string[];
|
||||
closedAt?: Date;
|
||||
metrics?: any;
|
||||
waitingResponse?: any;
|
||||
responseBy?: any;
|
||||
priorityId?: any;
|
||||
livechatData?: any;
|
||||
queuedAt?: Date;
|
||||
|
||||
ts: Date;
|
||||
label?: string;
|
||||
crmData?: unknown;
|
||||
message?: string;
|
||||
queueOrder?: string;
|
||||
estimatedWaitingTimeQueue?: string;
|
||||
estimatedServiceTimeAt?: Date;
|
||||
}
|
||||
|
||||
export type TRoomModel = IRoom & Model;
|
||||
|
|
|
@ -17,11 +17,11 @@ export enum SubscriptionType {
|
|||
}
|
||||
|
||||
export interface IVisitor {
|
||||
_id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
status: string;
|
||||
lastMessageTs: Date;
|
||||
_id?: string;
|
||||
token?: string;
|
||||
status: 'online' | 'busy' | 'away' | 'offline';
|
||||
username?: string;
|
||||
lastMessageTs?: Date;
|
||||
}
|
||||
|
||||
export enum ERoomTypes {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// ACTIONS
|
||||
import { TActionInquiry } from '../../ee/omnichannel/actions/inquiry';
|
||||
import { TActionActiveUsers } from '../../actions/activeUsers';
|
||||
import { TActionApp } from '../../actions/app';
|
||||
import { TActionCreateChannel } from '../../actions/createChannel';
|
||||
|
@ -30,6 +31,7 @@ import { ISelectedUsers } from '../../reducers/selectedUsers';
|
|||
import { IServer } from '../../reducers/server';
|
||||
import { TSettingsState } from '../../reducers/settings';
|
||||
import { IShare } from '../../reducers/share';
|
||||
import { IInquiry } from '../../ee/omnichannel/reducers/inquiry';
|
||||
import { IPermissionsState } from '../../reducers/permissions';
|
||||
import { IEnterpriseModules } from '../../reducers/enterpriseModules';
|
||||
|
||||
|
@ -50,7 +52,7 @@ export interface IApplicationState {
|
|||
usersTyping: any;
|
||||
inviteLinks: IInviteLinks;
|
||||
createDiscussion: ICreateDiscussion;
|
||||
inquiry: any;
|
||||
inquiry: IInquiry;
|
||||
enterpriseModules: IEnterpriseModules;
|
||||
encryption: IEncryption;
|
||||
permissions: IPermissionsState;
|
||||
|
@ -71,5 +73,6 @@ export type TApplicationActions = TActionActiveUsers &
|
|||
TActionsShare &
|
||||
TActionServer &
|
||||
TActionApp &
|
||||
TActionInquiry &
|
||||
TActionPermissions &
|
||||
TActionEnterpriseModules;
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
import * as types from '../../../actions/actionsTypes';
|
||||
|
||||
export function inquirySetEnabled(enabled) {
|
||||
return {
|
||||
type: types.INQUIRY.SET_ENABLED,
|
||||
enabled
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryReset() {
|
||||
return {
|
||||
type: types.INQUIRY.RESET
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueAdd(inquiry) {
|
||||
return {
|
||||
type: types.INQUIRY.QUEUE_ADD,
|
||||
inquiry
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueUpdate(inquiry) {
|
||||
return {
|
||||
type: types.INQUIRY.QUEUE_UPDATE,
|
||||
inquiry
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueRemove(inquiryId) {
|
||||
return {
|
||||
type: types.INQUIRY.QUEUE_REMOVE,
|
||||
inquiryId
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryRequest() {
|
||||
return {
|
||||
type: types.INQUIRY.REQUEST
|
||||
};
|
||||
}
|
||||
|
||||
export function inquirySuccess(inquiries) {
|
||||
return {
|
||||
type: types.INQUIRY.SUCCESS,
|
||||
inquiries
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryFailure(error) {
|
||||
return {
|
||||
type: types.INQUIRY.FAILURE,
|
||||
error
|
||||
};
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IOmnichannelRoom } from '../../../definitions';
|
||||
import { INQUIRY } from '../../../actions/actionsTypes';
|
||||
|
||||
interface IInquirySetEnabled extends Action {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
interface IInquiryQueueAddAndUpdate extends Action {
|
||||
inquiry: IOmnichannelRoom;
|
||||
}
|
||||
|
||||
interface IInquirySuccess extends Action {
|
||||
inquiries: IOmnichannelRoom[];
|
||||
}
|
||||
|
||||
interface IInquiryQueueRemove extends Action {
|
||||
inquiryId: string;
|
||||
}
|
||||
|
||||
interface IInquiryFailure extends Action {
|
||||
error: unknown;
|
||||
}
|
||||
|
||||
export type TActionInquiry = IInquirySetEnabled &
|
||||
IInquiryQueueAddAndUpdate &
|
||||
IInquirySuccess &
|
||||
IInquiryQueueRemove &
|
||||
IInquiryFailure;
|
||||
|
||||
export function inquirySetEnabled(enabled: boolean): IInquirySetEnabled {
|
||||
return {
|
||||
type: INQUIRY.SET_ENABLED,
|
||||
enabled
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryReset(): Action {
|
||||
return {
|
||||
type: INQUIRY.RESET
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueAdd(inquiry: IOmnichannelRoom): IInquiryQueueAddAndUpdate {
|
||||
return {
|
||||
type: INQUIRY.QUEUE_ADD,
|
||||
inquiry
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueUpdate(inquiry: IOmnichannelRoom): IInquiryQueueAddAndUpdate {
|
||||
return {
|
||||
type: INQUIRY.QUEUE_UPDATE,
|
||||
inquiry
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryQueueRemove(inquiryId: string): IInquiryQueueRemove {
|
||||
return {
|
||||
type: INQUIRY.QUEUE_REMOVE,
|
||||
inquiryId
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryRequest(): Action {
|
||||
return {
|
||||
type: INQUIRY.REQUEST
|
||||
};
|
||||
}
|
||||
|
||||
export function inquirySuccess(inquiries: IOmnichannelRoom[]): IInquirySuccess {
|
||||
return {
|
||||
type: INQUIRY.SUCCESS,
|
||||
inquiries
|
||||
};
|
||||
}
|
||||
|
||||
export function inquiryFailure(error: unknown): IInquiryFailure {
|
||||
return {
|
||||
type: INQUIRY.FAILURE,
|
||||
error
|
||||
};
|
||||
}
|
|
@ -1,19 +1,28 @@
|
|||
import React, { memo, useEffect, useState } from 'react';
|
||||
import { Switch, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import * as List from '../../../containers/List';
|
||||
import styles from '../../../views/RoomsListView/styles';
|
||||
import { SWITCH_TRACK_COLOR, themes } from '../../../constants/colors';
|
||||
import { withTheme } from '../../../theme';
|
||||
import { useTheme } from '../../../theme';
|
||||
import UnreadBadge from '../../../presentation/UnreadBadge';
|
||||
import RocketChat from '../../../lib/rocketchat';
|
||||
import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../lib';
|
||||
import { IUser } from '../../../definitions/IUser';
|
||||
|
||||
const OmnichannelStatus = memo(({ searching, goQueue, theme, queueSize, inquiryEnabled, user }) => {
|
||||
if (searching > 0 || !(RocketChat.isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) {
|
||||
interface IOmnichannelStatus {
|
||||
searching: boolean;
|
||||
goQueue: () => void;
|
||||
queueSize: number;
|
||||
inquiryEnabled: boolean;
|
||||
user: IUser;
|
||||
}
|
||||
|
||||
const OmnichannelStatus = memo(({ searching, goQueue, queueSize, inquiryEnabled, user }: IOmnichannelStatus) => {
|
||||
if (searching || !(RocketChat.isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) {
|
||||
return null;
|
||||
}
|
||||
const { theme } = useTheme();
|
||||
const [status, setStatus] = useState(isOmnichannelStatusAvailable(user));
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -48,16 +57,4 @@ const OmnichannelStatus = memo(({ searching, goQueue, theme, queueSize, inquiryE
|
|||
);
|
||||
});
|
||||
|
||||
OmnichannelStatus.propTypes = {
|
||||
searching: PropTypes.bool,
|
||||
goQueue: PropTypes.func,
|
||||
queueSize: PropTypes.number,
|
||||
inquiryEnabled: PropTypes.bool,
|
||||
theme: PropTypes.string,
|
||||
user: PropTypes.shape({
|
||||
roles: PropTypes.array,
|
||||
statusLivechat: PropTypes.string
|
||||
})
|
||||
};
|
||||
|
||||
export default withTheme(OmnichannelStatus);
|
||||
export default OmnichannelStatus;
|
|
@ -1,21 +1,24 @@
|
|||
import RocketChat from '../../../lib/rocketchat';
|
||||
import sdk from '../../../lib/rocketchat/services/sdk';
|
||||
import { IUser } from '../../../definitions';
|
||||
import EventEmitter from '../../../utils/events';
|
||||
import subscribeInquiry from './subscriptions/inquiry';
|
||||
|
||||
export const isOmnichannelStatusAvailable = user => user?.statusLivechat === 'available';
|
||||
export const isOmnichannelStatusAvailable = (user: IUser): boolean => user?.statusLivechat === 'available';
|
||||
|
||||
// RC 0.26.0
|
||||
export const changeLivechatStatus = () => RocketChat.methodCallWrapper('livechat:changeLivechatStatus');
|
||||
export const changeLivechatStatus = () => sdk.methodCallWrapper('livechat:changeLivechatStatus');
|
||||
|
||||
// RC 2.4.0
|
||||
export const getInquiriesQueued = () => RocketChat.sdk.get('livechat/inquiries.queued');
|
||||
// @ts-ignore
|
||||
export const getInquiriesQueued = () => sdk.get('livechat/inquiries.queued');
|
||||
|
||||
// this inquiry is added to the db by the subscriptions stream
|
||||
// and will be removed by the queue stream
|
||||
// RC 2.4.0
|
||||
export const takeInquiry = inquiryId => RocketChat.methodCallWrapper('livechat:takeInquiry', inquiryId);
|
||||
export const takeInquiry = (inquiryId: string) => sdk.methodCallWrapper('livechat:takeInquiry', inquiryId);
|
||||
|
||||
class Omnichannel {
|
||||
private inquirySub: { stop: () => void } | null;
|
||||
constructor() {
|
||||
this.inquirySub = null;
|
||||
EventEmitter.addEventListener('INQUIRY_SUBSCRIBE', this.subscribeInquiry);
|
||||
|
@ -36,5 +39,5 @@ class Omnichannel {
|
|||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const omnichannel = new Omnichannel();
|
|
@ -2,11 +2,28 @@ import log from '../../../../utils/log';
|
|||
import { store } from '../../../../lib/auxStore';
|
||||
import RocketChat from '../../../../lib/rocketchat';
|
||||
import { inquiryQueueAdd, inquiryQueueRemove, inquiryQueueUpdate, inquiryRequest } from '../../actions/inquiry';
|
||||
import sdk from '../../../../lib/rocketchat/services/sdk';
|
||||
import { ILivechatDepartment } from '../../../../definitions/ILivechatDepartment';
|
||||
import { IOmnichannelRoom } from '../../../../definitions';
|
||||
|
||||
const removeListener = listener => listener.stop();
|
||||
interface IArgsQueueOmnichannel extends IOmnichannelRoom {
|
||||
type: string;
|
||||
}
|
||||
|
||||
let connectedListener;
|
||||
let queueListener;
|
||||
interface IDdpMessage {
|
||||
msg: string;
|
||||
collection: string;
|
||||
id: string;
|
||||
fields: {
|
||||
eventName: string;
|
||||
args: IArgsQueueOmnichannel[];
|
||||
};
|
||||
}
|
||||
|
||||
const removeListener = (listener: any) => listener.stop();
|
||||
|
||||
let connectedListener: any;
|
||||
let queueListener: any;
|
||||
|
||||
const streamTopic = 'stream-livechat-inquiry-queue-observer';
|
||||
|
||||
|
@ -15,7 +32,7 @@ export default function subscribeInquiry() {
|
|||
store.dispatch(inquiryRequest());
|
||||
};
|
||||
|
||||
const handleQueueMessageReceived = ddpMessage => {
|
||||
const handleQueueMessageReceived = (ddpMessage: IDdpMessage) => {
|
||||
const [{ type, ...sub }] = ddpMessage.fields.args;
|
||||
|
||||
// added can be ignored, since it is handled by 'changed' event
|
||||
|
@ -26,7 +43,9 @@ export default function subscribeInquiry() {
|
|||
// if the sub isn't on the queue anymore
|
||||
if (sub.status !== 'queued') {
|
||||
// remove it from the queue
|
||||
store.dispatch(inquiryQueueRemove(sub._id));
|
||||
if (sub._id) {
|
||||
store.dispatch(inquiryQueueRemove(sub._id));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -53,23 +72,28 @@ export default function subscribeInquiry() {
|
|||
}
|
||||
};
|
||||
|
||||
connectedListener = RocketChat.onStreamData('connected', handleConnection);
|
||||
queueListener = RocketChat.onStreamData(streamTopic, handleQueueMessageReceived);
|
||||
connectedListener = sdk.onStreamData('connected', handleConnection);
|
||||
queueListener = sdk.onStreamData(streamTopic, handleQueueMessageReceived);
|
||||
|
||||
try {
|
||||
const { user } = store.getState().login;
|
||||
RocketChat.getAgentDepartments(user.id).then(result => {
|
||||
|
||||
if (!user.id) {
|
||||
throw new Error('inquiry: @subscribeInquiry user.id not found');
|
||||
}
|
||||
|
||||
RocketChat.getAgentDepartments(user.id).then((result: { success: boolean; departments: ILivechatDepartment[] }) => {
|
||||
if (result.success) {
|
||||
const { departments } = result;
|
||||
|
||||
if (!departments.length || RocketChat.hasRole('livechat-manager')) {
|
||||
RocketChat.subscribe(streamTopic, 'public').catch(e => console.log(e));
|
||||
sdk.subscribe(streamTopic, 'public').catch((e: unknown) => console.log(e));
|
||||
}
|
||||
|
||||
const departmentIds = departments.map(({ departmentId }) => departmentId);
|
||||
departmentIds.forEach(departmentId => {
|
||||
// subscribe to all departments of the agent
|
||||
RocketChat.subscribe(streamTopic, `department/${departmentId}`).catch(e => console.log(e));
|
||||
sdk.subscribe(streamTopic, `department/${departmentId}`).catch((e: unknown) => console.log(e));
|
||||
});
|
||||
}
|
||||
});
|
|
@ -0,0 +1,98 @@
|
|||
import {
|
||||
inquiryFailure,
|
||||
inquiryQueueAdd,
|
||||
inquiryQueueRemove,
|
||||
inquiryQueueUpdate,
|
||||
inquiryReset,
|
||||
inquirySetEnabled,
|
||||
inquirySuccess
|
||||
} from '../actions/inquiry';
|
||||
import { mockedStore } from '../../../reducers/mockedStore';
|
||||
import { initialState } from './inquiry';
|
||||
import { IOmnichannelRoom, OmnichannelSourceType, SubscriptionType } from '../../../definitions';
|
||||
|
||||
describe('test inquiry reduce', () => {
|
||||
const enabledObj = {
|
||||
enabled: true
|
||||
};
|
||||
|
||||
const queued: IOmnichannelRoom = {
|
||||
_id: '_id',
|
||||
rid: 'rid',
|
||||
name: 'Rocket Chat',
|
||||
ts: new Date(),
|
||||
message: 'ola',
|
||||
status: 'queued',
|
||||
v: {
|
||||
_id: 'id-visitor',
|
||||
username: 'guest-24',
|
||||
token: '123456789',
|
||||
status: 'online'
|
||||
},
|
||||
t: SubscriptionType.OMNICHANNEL,
|
||||
queueOrder: '1',
|
||||
estimatedWaitingTimeQueue: '0',
|
||||
estimatedServiceTimeAt: new Date(),
|
||||
source: {
|
||||
type: OmnichannelSourceType.WIDGET,
|
||||
_updatedAt: new Date(),
|
||||
queuedAt: new Date()
|
||||
}
|
||||
};
|
||||
|
||||
const error = 'Error Test';
|
||||
|
||||
it('should return inital state', () => {
|
||||
const state = mockedStore.getState().inquiry;
|
||||
expect(state).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct inquiry state after dispatch inquirySetEnabled action', () => {
|
||||
mockedStore.dispatch(inquirySetEnabled(enabledObj.enabled));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual({ ...initialState, ...enabledObj });
|
||||
});
|
||||
|
||||
it('after inquiry state is modified, should return inquiry state as initial state after dispatch inquiryReset action', () => {
|
||||
mockedStore.dispatch(inquiryReset());
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct inquiry state after dispatch inquiryQueueAdd action', () => {
|
||||
mockedStore.dispatch(inquiryQueueAdd(queued));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual({ ...initialState, queued: [queued] });
|
||||
});
|
||||
|
||||
it('should update correct inquiry state after dispatch inquiryQueueUpdate action', () => {
|
||||
const modifiedQueued: IOmnichannelRoom = { ...queued, message: 'inquiryQueueUpdate' };
|
||||
mockedStore.dispatch(inquiryQueueUpdate(modifiedQueued));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual({ ...initialState, queued: [modifiedQueued] });
|
||||
});
|
||||
|
||||
it('should remove correct from queue in inquiry state after dispatch inquiryQueueRemove action', () => {
|
||||
mockedStore.dispatch(inquiryQueueRemove(queued._id));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct inquiry state after dispatch inquirySuccess action', () => {
|
||||
mockedStore.dispatch(inquirySuccess([queued]));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual({ ...initialState, queued: [queued] });
|
||||
});
|
||||
|
||||
it('after inquiry state is modified, should return inquiry state as initial state after dispatch inquiryReset action', () => {
|
||||
mockedStore.dispatch(inquiryReset());
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct inquiry state after dispatch inquiryFailure action', () => {
|
||||
mockedStore.dispatch(inquiryFailure(error));
|
||||
const { inquiry } = mockedStore.getState();
|
||||
expect(inquiry).toEqual({ ...initialState, error });
|
||||
});
|
||||
});
|
|
@ -1,12 +1,19 @@
|
|||
import { IOmnichannelRoom, TApplicationActions } from '../../../definitions';
|
||||
import { INQUIRY } from '../../../actions/actionsTypes';
|
||||
|
||||
const initialState = {
|
||||
export interface IInquiry {
|
||||
enabled: boolean;
|
||||
queued: IOmnichannelRoom[];
|
||||
error: any;
|
||||
}
|
||||
|
||||
export const initialState: IInquiry = {
|
||||
enabled: false,
|
||||
queued: [],
|
||||
error: {}
|
||||
};
|
||||
|
||||
export default function inquiry(state = initialState, action) {
|
||||
export default function inquiry(state = initialState, action: TApplicationActions): IInquiry {
|
||||
switch (action.type) {
|
||||
case INQUIRY.SUCCESS:
|
||||
return {
|
|
@ -1,5 +1,7 @@
|
|||
import { createSelector } from 'reselect';
|
||||
|
||||
const getInquiryQueue = state => state.inquiry.queued;
|
||||
import { IApplicationState } from '../../../definitions';
|
||||
|
||||
const getInquiryQueue = (state: IApplicationState) => state.inquiry.queued;
|
||||
|
||||
export const getInquiryQueueSelector = createSelector([getInquiryQueue], queue => queue);
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FlatList } from 'react-native';
|
||||
import { CompositeNavigationProp } from '@react-navigation/native';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
import { FlatList, ListRenderItem } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
|
@ -19,18 +20,50 @@ import * as HeaderButton from '../../../containers/HeaderButton';
|
|||
import RocketChat from '../../../lib/rocketchat';
|
||||
import { events, logEvent } from '../../../utils/log';
|
||||
import { getInquiryQueueSelector } from '../selectors/inquiry';
|
||||
import { IOmnichannelRoom, IApplicationState } from '../../../definitions';
|
||||
import { DisplayMode } from '../../../constants/constantDisplayMode';
|
||||
import { ChatsStackParamList } from '../../../stacks/types';
|
||||
import { MasterDetailInsideStackParamList } from '../../../stacks/MasterDetailStack/types';
|
||||
import { TSettingsValues } from '../../../reducers/settings';
|
||||
|
||||
interface INavigationOptions {
|
||||
isMasterDetail: boolean;
|
||||
navigation: CompositeNavigationProp<
|
||||
StackNavigationProp<ChatsStackParamList, 'QueueListView'>,
|
||||
StackNavigationProp<MasterDetailInsideStackParamList>
|
||||
>;
|
||||
}
|
||||
|
||||
interface IQueueListView extends INavigationOptions {
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
};
|
||||
width: number;
|
||||
queued: IOmnichannelRoom[];
|
||||
server: string;
|
||||
useRealName?: TSettingsValues;
|
||||
theme: string;
|
||||
showAvatar: any;
|
||||
displayMode: DisplayMode;
|
||||
}
|
||||
|
||||
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
|
||||
const getItemLayout = (data, index) => ({
|
||||
const getItemLayout = (data: IOmnichannelRoom[] | null | undefined, index: number) => ({
|
||||
length: ROW_HEIGHT,
|
||||
offset: ROW_HEIGHT * index,
|
||||
index
|
||||
});
|
||||
const keyExtractor = item => item.rid;
|
||||
const keyExtractor = (item: IOmnichannelRoom) => item.rid;
|
||||
|
||||
class QueueListView extends React.Component {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }) => {
|
||||
const options = {
|
||||
class QueueListView extends React.Component<IQueueListView, any> {
|
||||
private getScrollRef?: React.Ref<FlatList<IOmnichannelRoom>>;
|
||||
|
||||
private onEndReached: ((info: { distanceFromEnd: number }) => void) | null | undefined;
|
||||
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: INavigationOptions) => {
|
||||
const options: StackNavigationOptions = {
|
||||
title: I18n.t('Queued_chats')
|
||||
};
|
||||
if (isMasterDetail) {
|
||||
|
@ -39,24 +72,7 @@ class QueueListView extends React.Component {
|
|||
return options;
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
username: PropTypes.string,
|
||||
token: PropTypes.string
|
||||
}),
|
||||
isMasterDetail: PropTypes.bool,
|
||||
width: PropTypes.number,
|
||||
queued: PropTypes.array,
|
||||
server: PropTypes.string,
|
||||
useRealName: PropTypes.bool,
|
||||
navigation: PropTypes.object,
|
||||
theme: PropTypes.string,
|
||||
showAvatar: PropTypes.bool,
|
||||
displayMode: PropTypes.string
|
||||
};
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
shouldComponentUpdate(nextProps: IQueueListView) {
|
||||
const { queued } = this.props;
|
||||
if (!dequal(nextProps.queued, queued)) {
|
||||
return true;
|
||||
|
@ -65,7 +81,7 @@ class QueueListView extends React.Component {
|
|||
return false;
|
||||
}
|
||||
|
||||
onPressItem = (item = {}) => {
|
||||
onPressItem = (item = {} as IOmnichannelRoom) => {
|
||||
logEvent(events.QL_GO_ROOM);
|
||||
const { navigation, isMasterDetail } = this.props;
|
||||
if (isMasterDetail) {
|
||||
|
@ -84,13 +100,13 @@ class QueueListView extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
getRoomTitle = item => RocketChat.getRoomTitle(item);
|
||||
getRoomTitle = (item: IOmnichannelRoom) => RocketChat.getRoomTitle(item);
|
||||
|
||||
getRoomAvatar = item => RocketChat.getRoomAvatar(item);
|
||||
getRoomAvatar = (item: IOmnichannelRoom) => RocketChat.getRoomAvatar(item);
|
||||
|
||||
getUidDirectMessage = room => RocketChat.getUidDirectMessage(room);
|
||||
getUidDirectMessage = (room: IOmnichannelRoom) => RocketChat.getUidDirectMessage(room);
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
renderItem: ListRenderItem<IOmnichannelRoom> = ({ item }) => {
|
||||
const {
|
||||
user: { id: userId, username, token },
|
||||
server,
|
||||
|
@ -152,7 +168,7 @@ class QueueListView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
const mapStateToProps = (state: IApplicationState) => ({
|
||||
user: getUserSelector(state),
|
||||
isMasterDetail: state.app.isMasterDetail,
|
||||
server: state.server.server,
|
|
@ -1,7 +1,7 @@
|
|||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import Navigation from '../lib/Navigation';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import { ISubscription, IVisitor, SubscriptionType, TSubscriptionModel } from '../definitions/ISubscription';
|
||||
import { IOmnichannelRoom, SubscriptionType, IVisitor, TSubscriptionModel, ISubscription } from '../definitions';
|
||||
|
||||
interface IGoRoomItem {
|
||||
search?: boolean; // comes from spotlight
|
||||
|
@ -13,7 +13,7 @@ interface IGoRoomItem {
|
|||
visitor?: IVisitor;
|
||||
}
|
||||
|
||||
export type TGoRoomItem = IGoRoomItem | TSubscriptionModel | ISubscription;
|
||||
export type TGoRoomItem = IGoRoomItem | TSubscriptionModel | ISubscription | IOmnichannelRoomVisitor;
|
||||
|
||||
const navigate = ({
|
||||
item,
|
||||
|
@ -42,6 +42,11 @@ const navigate = ({
|
|||
});
|
||||
};
|
||||
|
||||
interface IOmnichannelRoomVisitor extends IOmnichannelRoom {
|
||||
// this visitor came from ee/omnichannel/views/QueueListView
|
||||
visitor: IVisitor;
|
||||
}
|
||||
|
||||
export const goRoom = async ({
|
||||
item,
|
||||
isMasterDetail = false,
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
export interface ILivechatDepartment {
|
||||
_id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
description: string;
|
||||
showOnRegistration: boolean;
|
||||
showOnOfflineForm: boolean;
|
||||
requestTagBeforeClosingChat: boolean;
|
||||
email: string;
|
||||
chatClosingTags: string[];
|
||||
offlineMessageChannelName: string;
|
||||
numAgents: number;
|
||||
_updatedAt?: Date;
|
||||
businessHourId?: string;
|
||||
}
|
Loading…
Reference in New Issue