Skip to content

Commit

Permalink
Happychat: Persist transcripts between reloads (#11662)
Browse files Browse the repository at this point in the history
* Happychat: Persist chat history

* Schema to validate timeline

* Persist stringy timestamps

* Ensure timeline is sorted when transcript received
  • Loading branch information
jordwest authored and mattwondra committed Mar 27, 2017
1 parent eff1c17 commit b1479af
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
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,
};

0 comments on commit b1479af

Please sign in to comment.