Skip to content

feat(admin): add CampaignType to campaign + Call table - #194

Merged
sukhada merged 10 commits into
dialerfrom
dialer-campaign-type
Jun 17, 2026
Merged

feat(admin): add CampaignType to campaign + Call table#194
sukhada merged 10 commits into
dialerfrom
dialer-campaign-type

Conversation

@sukhada

@sukhada sukhada commented Jun 4, 2026

Copy link
Copy Markdown
  • Add CampaignType (SMS or CALL) to campaign
  • Add new Call table
  • Rename texter -> volunteer in admin UI

@sukhada
sukhada requested a review from ajohn25 June 4, 2026 14:08
@ajohn25

ajohn25 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

@sukhada i think rather than overloading (in both the inheritance and performance sense potentially) the current tables, it might make sense to create separate ones for the dialer that only include the columns relevant for dialer (ex. dialer_campaign, dialer_campaign_contact ).

From previous analysis, the current tables aren't even well optimized for texting workloads, so I'd hesitate to extend them to cover dialer as well.

In my mind the ideal would eventually be something like:
campaign_contact - including columns shared by texting + dialer
texting_campaign_contact - including columns used just by texting (in particular the dynamic ones)
dialer_campaign_contact - including columns used just by dialer

This also helps avoid weird possible states (ex. what happens if a dialer campaign accidentally gets set to autosend_status = 'sending')

But to avoid extra changes to texting campaigns at this point, and because the dialer data structure could be somewhat fluid for a bit, I think leaving the existing tables alone for now and putting everything dialer related into their own tables might be a happy medium. Lmk what you think!

*edit: Edited this comment to reflect this is more of a concern with using campaign_contact rather than campaign which has less dynamic columns

@ajohn25 ajohn25 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewing non campaign_contact related things for now!

Comment thread libs/gql-schema/campaign.ts
Comment thread src/containers/AdminCampaignEdit/sections/CampaignTypeForm.tsx Outdated
Comment thread src/containers/AdminCampaignEdit/sections/CampaignTypeForm.tsx Outdated
Comment thread src/containers/AdminCampaignEdit/sections/CampaignTypeForm.tsx Outdated
Comment thread src/containers/AdminCampaignEdit/sections/CampaignTypeForm.tsx Outdated
Comment thread src/server/api/lib/campaign.ts Outdated
Comment thread src/server/api/campaign.js
Comment thread src/server/api/types.ts Outdated
Comment thread migrations/20260601000001_add-campaign-type.js
Comment thread migrations/20260601000003_create-dialer-call.js
@sukhada
sukhada requested a review from ajohn25 June 6, 2026 15:03

@ajohn25 ajohn25 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required: Will need to run update-dump.sh to update schema-dump.sql

Comment thread migrations/20260601000001_add-campaign-type.js Outdated
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js Outdated
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js Outdated
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js Outdated
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js Outdated
Comment thread migrations/20260601000004_create-dialer-question-response.js
* @returns { Promise<void> }
*/
exports.up = async function up(knex) {
await knex.schema.createTable("dialer_question_response", (table) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Intentional decision to skip the "all responses in larger table" all_question_response, "current responses in view" question_response pattern? I think if we're committing to dialer survey answers not being editable this makes sense, but if we do want to leave the door open for that, might need to do similar

Comment thread migrations/20260601000005_create-dialer-campaign-contact-tag.js Outdated
Comment thread migrations/20260601000005_create-dialer-campaign-contact-tag.js Outdated
Comment thread migrations/20260601000005_create-dialer-campaign-contact-tag.js
Comment thread migrations/20260601000005_create-dialer-campaign-contact-tag.js
@sukhada
sukhada requested a review from ajohn25 June 8, 2026 21:14
@sukhada
sukhada force-pushed the dialer-campaign-type branch from 110a0b3 to 4243fe2 Compare June 9, 2026 00:15
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js Outdated
Comment thread migrations/20260601000002_create-dialer-campaign-contact.js
Comment on lines +35 to +36
// queries. The composite (contact_id, status) index also covers the NOT EXISTS
// subqueries that filter callable contacts by active/terminal call status.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: AKA we could later use this to distinguish btwn calls that are picked up and aren't to mark second passes right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah although I think we could just filter calls with the status NO_ANSWER for that as well!

Comment thread migrations/20260601000005_create-dialer-campaign-contact-tag.js
sukhada and others added 3 commits June 10, 2026 06:22
* feat(dialer): volunteer caller backend (Design-B call tracking)

Backend for the volunteer dialer, stacked on dialer-campaign-type:
- GraphQL schema, resolvers, and Telnyx WebRTC token route
- dialer lib: shift assignment, contact-hours-aware serving, atomic
  call_status claim, disposition + attempt tracking
- forward migrations (campaign-type's create migrations left untouched):
  - 000009: drop call_campaigns_no_autoassign (call campaigns use autoassign
    for shifts)
  - 000010: add call_status/attempt_count/last_attempted_at to
    dialer_campaign_contact and disposition to dialer_call

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(dialer): address feedback

* feat(dialer): volunteer caller frontend (Telnyx WebRTC UI)  (#207)

* chore(tool-versions): update node version (#195)

* feat(dialer): volunteer caller frontend (Telnyx WebRTC UI)

Frontend for the volunteer dialer, stacked on dialer-backend:
- VolunteerDialer container: WebRTC call controls, timer, status bar,
  disposition form, contact flow
- TexterTodoList: call-shift request entry point (CallRequest) and
  call-aware assignment summary
- AdminCampaignStats: call-campaign stat tweaks
- dialer GraphQL operations (hooks) and @telnyx/webrtc dependency

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dialer): add canned responses + tags to calling (#208)

* feat(dialer): add canned responses + tags to calling

* feat(dialer): allow releasing calls (#209)

* feat(dialer): allow releasing calls

* feat(dialer): add texting history to call screen (#210)

* feat(dialer): add texting history to call screen

* chore: update seeds to not use logger.info

* chore(dialer): fix variable interpolation in script

---------

Co-authored-by: Aashish John <aashishjohn25@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Aashish John <aashishjohn25@gmail.com>
@sukhada
sukhada merged commit c94a8ea into dialer Jun 17, 2026
5 checks passed
@sukhada
sukhada deleted the dialer-campaign-type branch June 17, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants