Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Happychat: Persist transcripts between reloads #11662

Merged
merged 4 commits into from Mar 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/state/happychat/constants.js
@@ -0,0 +1,2 @@
// Max number of messages to save between refreshes
export const HAPPYCHAT_MAX_STORED_MESSAGES = 30;
32 changes: 23 additions & 9 deletions client/state/happychat/reducer.js
Expand Up @@ -2,11 +2,16 @@
* External dependencies
*/
import { combineReducers } from 'redux';
import get from 'lodash/get';
import find from 'lodash/find';
import concat from 'lodash/concat';
import filter from 'lodash/filter';
import map from 'lodash/map';
import {
concat,
filter,
find,
map,
get,
sortBy,
takeRight,
} from 'lodash';
import validator from 'is-my-json-valid';

/**
* Internal dependencies
Expand All @@ -22,6 +27,8 @@ import {
HAPPYCHAT_SET_CHAT_STATUS,
HAPPYCHAT_TRANSCRIPT_RECEIVE,
} from 'state/action-types';
import { HAPPYCHAT_MAX_STORED_MESSAGES } from './constants';
import { timelineSchema } from './schema';

/**
* Returns a timeline event from the redux action
Expand Down Expand Up @@ -50,6 +57,9 @@ const timeline_event = ( state = {}, action ) => {
return state;
};

const validateTimeline = validator( timelineSchema );
const sortTimeline = timeline => sortBy( timeline, event => parseInt( event.timestamp, 10 ) );

/**
* Adds timeline events for happychat
*
Expand All @@ -61,9 +71,13 @@ const timeline_event = ( state = {}, action ) => {
const timeline = ( state = [], action ) => {
switch ( action.type ) {
case SERIALIZE:
return [];
return takeRight( state, HAPPYCHAT_MAX_STORED_MESSAGES );
case DESERIALIZE:
return state;
const valid = validateTimeline( state );
if ( valid ) {
return state;
}
return [];
case HAPPYCHAT_RECEIVE_EVENT:
// if meta.forOperator is set, skip so won't show to user
if ( get( action, 'event.meta.forOperator', false ) ) {
Expand All @@ -85,7 +99,7 @@ const timeline = ( state = [], action ) => {

return ! find( state, { id: message.id } );
} );
return state.concat( map( messages, message => {
return sortTimeline( state.concat( map( messages, message => {
return Object.assign( {
id: message.id,
source: message.source,
Expand All @@ -97,7 +111,7 @@ const timeline = ( state = [], action ) => {
type: get( message, 'type', 'message' ),
links: get( message, 'meta.links' )
} );
} ) );
} ) ) );
}
return state;
};
Expand Down
29 changes: 29 additions & 0 deletions client/state/happychat/schema.js
@@ -0,0 +1,29 @@

export const eventSchema = {
type: 'object',
additionalProperties: false,
required: [
'id',
'source',
'message',
'timestamp',
'user_id',
'type' ],
properties: {
id: { type: 'string' },
source: { type: 'string' },
message: { type: 'string' },
name: { type: 'string' },
image: { type: 'string' },
timestamp: { type: [ 'number', 'string' ] },
user_id: { type: [ 'number', 'string' ] },
type: { type: 'string' },
links: { type: 'array' },
}
};

export const timelineSchema = {
type: 'array',
additionalProperties: false,
items: eventSchema,
};