From 960d0bb263b6f773d2afea6aa7064bb7d12d2fe0 Mon Sep 17 00:00:00 2001 From: Larry Date: Wed, 13 Jun 2018 18:32:43 -0400 Subject: [PATCH] refined query, wired in data from new query with data grid --- src/components/IncomingMessageList.jsx | 8 ++ src/server/api/assignment.js | 103 ++++++++++++++----------- src/server/api/schema.js | 15 ++-- 3 files changed, 76 insertions(+), 50 deletions(-) diff --git a/src/components/IncomingMessageList.jsx b/src/components/IncomingMessageList.jsx index af333b9a6..6c37f1671 100644 --- a/src/components/IncomingMessageList.jsx +++ b/src/components/IncomingMessageList.jsx @@ -41,6 +41,9 @@ function prepareSelectedRowsData(conversations, rowsSelected) { returnData.push({ campaignId: conversation.campaign.id, campaignContactId: conversation.contact.id, + messageIds: conversation.contact.messages.map(message => { + return message.id + }) }) return returnData }, []) @@ -255,6 +258,11 @@ const mapQueriesToProps = ({ ownProps }) => ({ firstName lastName messageStatus + messages { + id + text + isFromContact + } } campaign { id diff --git a/src/server/api/assignment.js b/src/server/api/assignment.js index ab36cce5c..7c1fdd6ff 100644 --- a/src/server/api/assignment.js +++ b/src/server/api/assignment.js @@ -1,6 +1,6 @@ -import {mapFieldsToModel} from './lib/utils' -import {Assignment, r} from '../models' -import {getOffsets, defaultTimezoneIsBetweenTextingHours} from '../../lib' +import { mapFieldsToModel } from './lib/utils' +import { Assignment, r } from '../models' +import { getOffsets, defaultTimezoneIsBetweenTextingHours } from '../../lib' export const schema = ` input AssignmentsFilter { @@ -30,10 +30,27 @@ function addWhereClauseForNeedsMessageOrResponse(query) { return addWhereClauseForMessageStatus(query, 'needsResponse,needsMessage') } -function hasOwnProperty(obj, propname){ +function hasOwnProperty(obj, propname) { return Object.prototype.hasOwnProperty.call(obj, propname) } +export function addWhereClauseForContactsFilterMessageStatusIrrespectiveOfPastDue( + queryParameter, + contactsFilter +) { + if (!contactsFilter || !('messageStatus' in contactsFilter)) { + return queryParameter + } + + let query = queryParameter + if (contactsFilter.messageStatus === 'needsMessageOrResponse') { + query = addWhereClauseForNeedsMessageOrResponse(query) + } else { + query = addWhereClauseForMessageStatus(query, contactsFilter.messageStatus) + } + return query +} + export function getContacts(assignment, contactsFilter, organization, campaign) { // / returns list of contacts eligible for contacting _now_ by a particular user const textingHoursEnforced = organization.texting_hours_enforced @@ -41,15 +58,15 @@ export function getContacts(assignment, contactsFilter, organization, campaign) const textingHoursEnd = organization.texting_hours_end // 24-hours past due - why is this 24 hours offset? - const pastDue = ((Number(campaign.due_by) + 24 * 60 * 60 * 1000) < Number(new Date())) + const pastDue = Number(campaign.due_by) + 24 * 60 * 60 * 1000 < Number(new Date()) - const config = {textingHoursStart, textingHoursEnd, textingHoursEnforced} + const config = { textingHoursStart, textingHoursEnd, textingHoursEnforced } const [validOffsets, invalidOffsets] = getOffsets(config) let query = r.knex('campaign_contact').where('assignment_id', assignment.id) if (contactsFilter) { - if (hasOwnProperty(contactsFilter,'validTimezone') && contactsFilter.validTimezone !== null) { + if (hasOwnProperty(contactsFilter, 'validTimezone') && contactsFilter.validTimezone !== null) { if (contactsFilter.validTimezone === true) { if (defaultTimezoneIsBetweenTextingHours(config)) { // missing timezone ok @@ -66,25 +83,30 @@ export function getContacts(assignment, contactsFilter, organization, campaign) } let includePastDue = false - if (hasOwnProperty(contactsFilter,'includePastDue') && contactsFilter.includePastDue != null) { + if (hasOwnProperty(contactsFilter, 'includePastDue') && contactsFilter.includePastDue != null) { includePastDue = contactsFilter.includePastDue } - if (includePastDue && hasOwnProperty(contactsFilter,'messageStatus') && contactsFilter.messageStatus !== null) { - if (contactsFilter.messageStatus === 'needsMessageOrResponse') { - query = addWhereClauseForNeedsMessageOrResponse(query) - } - else { - query = addWhereClauseForMessageStatus(query, contactsFilter.messageStatus) - } - + if ( + includePastDue && + hasOwnProperty(contactsFilter, 'messageStatus') && + contactsFilter.messageStatus !== null + ) { + query = addWhereClauseForContactsFilterMessageStatusIrrespectiveOfPastDue( + query, + contactsFilter + ) } else { - if (hasOwnProperty(contactsFilter,'messageStatus') && contactsFilter.messageStatus !== null) { + if ( + hasOwnProperty(contactsFilter, 'messageStatus') && + contactsFilter.messageStatus !== null + ) { if (pastDue && contactsFilter.messageStatus === 'needsMessage') { query = addWhereClauseForMessageStatus(query, '') // stops finding anything after pastDue } else if (contactsFilter.messageStatus === 'needsMessageOrResponse') { - query = addWhereClauseForNeedsMessageOrResponse(query) - .orderByRaw('message_status DESC, updated_at') + query = addWhereClauseForNeedsMessageOrResponse(query).orderByRaw( + 'message_status DESC, updated_at' + ) } else { query = addWhereClauseForMessageStatus(query, contactsFilter.messageStatus) } @@ -99,7 +121,7 @@ export function getContacts(assignment, contactsFilter, organization, campaign) } } - if (hasOwnProperty(contactsFilter,'isOptedOut') && contactsFilter.isOptedOut !== null) { + if (hasOwnProperty(contactsFilter, 'isOptedOut') && contactsFilter.isOptedOut !== null) { query = query.where('is_opted_out', contactsFilter.isOptedOut) } } @@ -109,38 +131,31 @@ export function getContacts(assignment, contactsFilter, organization, campaign) export const resolvers = { Assignment: { - ...mapFieldsToModel([ - 'id', - 'maxContacts' - ], Assignment), - texter: async (assignment, _, {loaders}) => ( - loaders.user.load(assignment.user_id) - ), - campaign: async (assignment, _, {loaders}) => loaders.campaign.load(assignment.campaign_id), - contactsCount: async (assignment, {contactsFilter}) => { + ...mapFieldsToModel(['id', 'maxContacts'], Assignment), + texter: async (assignment, _, { loaders }) => loaders.user.load(assignment.user_id), + campaign: async (assignment, _, { loaders }) => loaders.campaign.load(assignment.campaign_id), + contactsCount: async (assignment, { contactsFilter }) => { const campaign = await r.table('campaign').get(assignment.campaign_id) - const organization = await r.table('organization') - .get(campaign.organization_id) + const organization = await r.table('organization').get(campaign.organization_id) return await r.getCount(getContacts(assignment, contactsFilter, organization, campaign)) }, - contacts: async (assignment, {contactsFilter}) => { + contacts: async (assignment, { contactsFilter }) => { const campaign = await r.table('campaign').get(assignment.campaign_id) - const organization = await r.table('organization') - .get(campaign.organization_id) + const organization = await r.table('organization').get(campaign.organization_id) return getContacts(assignment, contactsFilter, organization, campaign) }, - campaignCannedResponses: async (assignment) => ( - await r.table('canned_response') - .getAll(assignment.campaign_id, {index: 'campaign_id'}) - .filter({user_id: ''}) - ), - userCannedResponses: async (assignment) => ( - await r.table('canned_response') - .getAll(assignment.campaign_id, {index: 'campaign_id'}) - .filter({user_id: assignment.user_id}) - ) + campaignCannedResponses: async assignment => + await r + .table('canned_response') + .getAll(assignment.campaign_id, { index: 'campaign_id' }) + .filter({ user_id: '' }), + userCannedResponses: async assignment => + await r + .table('canned_response') + .getAll(assignment.campaign_id, { index: 'campaign_id' }) + .filter({ user_id: assignment.user_id }) } } diff --git a/src/server/api/schema.js b/src/server/api/schema.js index a4f5c9fff..6c65b5419 100644 --- a/src/server/api/schema.js +++ b/src/server/api/schema.js @@ -22,7 +22,11 @@ import { schema as userSchema, resolvers as userResolvers } from './user' import { schema as conversationSchema, resolvers as conversationsResolver } from './conversations' import { schema as organizationSchema, resolvers as organizationResolvers } from './organization' import { schema as campaignSchema, resolvers as campaignResolvers } from './campaign' -import { schema as assignmentSchema, resolvers as assignmentResolvers } from './assignment' +import { + schema as assignmentSchema, + resolvers as assignmentResolvers, + addWhereClauseForContactsFilterMessageStatusIrrespectiveOfPastDue +} from './assignment' import { schema as interactionStepSchema, resolvers as interactionStepResolvers @@ -1346,11 +1350,14 @@ const rootResolvers = { 'campaign_contact.message_status', 'campaign_contact.is_opted_out', 'campaign_contact.updated_at', + 'campaign_contact.cell', + 'campaign_contact.assignment_id', 'user.id as u_id', 'user.first_name as u_first_name', 'user.last_name as u_last_name', 'campaign.id as cmp_id', 'campaign.title', + 'campaign.due_by', 'assignment.id as ass_id' ) .from('campaign') @@ -1373,11 +1380,7 @@ const rootResolvers = { query = query.where({ 'assignment.user_id': assignmentsFilter.texterId }) } - if (contactsFilter) { - - } - - return query + return addWhereClauseForContactsFilterMessageStatusIrrespectiveOfPastDue(query, contactsFilter) } } }