diff --git a/libs/gql-schema/schema.ts b/libs/gql-schema/schema.ts index a1526a757..1f204f033 100644 --- a/libs/gql-schema/schema.ts +++ b/libs/gql-schema/schema.ts @@ -48,6 +48,7 @@ const rootSchema = ` searchString: String! replaceString: String! campaignIds: [String!]! + organizationId: String! } input ContactActionInput { @@ -261,7 +262,7 @@ const rootSchema = ` notices(organizationId: String): NoticePage! campaignGroups(organizationId: String! after: Cursor, first: Int): CampaignGroupPage! campaignNavigation(campaignId: String!): CampaignNavigation! - bulkUpdateScriptChanges(organizationId: String!, findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateChange!]! + bulkUpdateScriptChanges(findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateChange!]! superadmins: [User!] optOuts(organizationId: String!): [OptOutByCampaign!]! isValidAttachment(fileUrl: String!): Boolean! @@ -282,7 +283,7 @@ const rootSchema = ` saveCampaignGroups(organizationId: String!, campaignGroups: [CampaignGroupInput!]!): [CampaignGroup!]! deleteCampaignGroup(organizationId: String!, campaignGroupId: String!): Boolean! filterLandlines(id:String!): Campaign - bulkUpdateScript(organizationId:String!, findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateResult] + bulkUpdateScript(findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateResult] deleteJob(campaignId:String!, id:String!): JobRequest copyCampaign(id: String!): Campaign copyCampaigns(sourceCampaignId: String!, quantity: Int!, targetOrgId: String): [Campaign!]! diff --git a/libs/spoke-codegen/src/graphql/bulk-script-editor.graphql b/libs/spoke-codegen/src/graphql/bulk-script-editor.graphql index bc5c312bb..3d28cd169 100644 --- a/libs/spoke-codegen/src/graphql/bulk-script-editor.graphql +++ b/libs/spoke-codegen/src/graphql/bulk-script-editor.graphql @@ -17,11 +17,9 @@ query GetCampaignsBulkScriptEditor( } query GetScriptUpdateChanges( - $organizationId: String! $findAndReplace: BulkUpdateScriptInput! ) { bulkUpdateScriptChanges( - organizationId: $organizationId findAndReplace: $findAndReplace ) { id @@ -32,11 +30,9 @@ query GetScriptUpdateChanges( } mutation BulkUpdateScript( - $organizationId: String! $findAndReplace: BulkUpdateScriptInput! ) { bulkUpdateScript( - organizationId: $organizationId findAndReplace: $findAndReplace ) { campaignId diff --git a/src/containers/AdminBulkScriptEditor/index.tsx b/src/containers/AdminBulkScriptEditor/index.tsx index b41c77d41..490d8d0b2 100644 --- a/src/containers/AdminBulkScriptEditor/index.tsx +++ b/src/containers/AdminBulkScriptEditor/index.tsx @@ -18,10 +18,15 @@ import { import groupBy from "lodash/groupBy"; import isEmpty from "lodash/isEmpty"; import React, { useState } from "react"; +import type { RouteChildrenProps } from "react-router-dom"; import { formatErrorMessage } from "../hoc/with-operations"; import ChangesDialog from "./components/ChangesDialog"; +type AdminBulkScriptEditorProps = RouteChildrenProps<{ + organizationId: string; +}>; + const PROTECTED_CHARACTERS = ["/"]; const styles = { @@ -40,7 +45,10 @@ const styles = { } }; -const AdminBulkScriptEditor: React.FC = (props) => { +const AdminBulkScriptEditor: React.FC = (props) => { + const organizationId = props.match?.params.organizationId; + if (!organizationId) return null; + const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(""); const [result, setResult] = useState(null); @@ -68,7 +76,7 @@ const AdminBulkScriptEditor: React.FC = (props) => { } = useGetCampaignsBulkScriptEditorQuery({ variables: { campaignsFilter, - organizationId: props.match.params.organizationId + organizationId } }); @@ -79,9 +87,9 @@ const AdminBulkScriptEditor: React.FC = (props) => { findAndReplace: { searchString, replaceString, - campaignIds: selectedCampaigns - }, - organizationId: props.match.params.organizationId + campaignIds: selectedCampaigns, + organizationId + } } }); @@ -90,9 +98,9 @@ const AdminBulkScriptEditor: React.FC = (props) => { findAndReplace: { replaceString, searchString, - campaignIds: selectedCampaigns - }, - organizationId: props.match.params.organizationId + campaignIds: selectedCampaigns, + organizationId + } } }); @@ -334,15 +342,25 @@ const AdminBulkScriptEditor: React.FC = (props) => { {`Updated ${result.length} Occurence(s)`}
    - {result.map(({ campaignId, found, replaced }) => ( -
  • - Campaign ID: {campaignId} -
    - Found: {found} -
    - Replaced with: {replaced} -
  • - ))} + {result.map( + ({ + campaignId, + found, + replaced + }: { + campaignId: string; + found: string; + replaced: string; + }) => ( +
  • + Campaign ID: {campaignId} +
    + Found: {found} +
    + Replaced with: {replaced} +
  • + ) + )}
{result.length === 0 && ( diff --git a/src/schema.graphql b/src/schema.graphql index 1976af0c9..d3b209692 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -14,6 +14,7 @@ input BulkUpdateScriptInput { searchString: String! replaceString: String! campaignIds: [String!]! + organizationId: String! } input ContactActionInput { @@ -227,7 +228,7 @@ type RootQuery { notices(organizationId: String): NoticePage! campaignGroups(organizationId: String! after: Cursor, first: Int): CampaignGroupPage! campaignNavigation(campaignId: String!): CampaignNavigation! - bulkUpdateScriptChanges(organizationId: String!, findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateChange!]! + bulkUpdateScriptChanges(findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateChange!]! superadmins: [User!] optOuts(organizationId: String!): [OptOutByCampaign!]! isValidAttachment(fileUrl: String!): Boolean! @@ -248,7 +249,7 @@ type RootMutation { saveCampaignGroups(organizationId: String!, campaignGroups: [CampaignGroupInput!]!): [CampaignGroup!]! deleteCampaignGroup(organizationId: String!, campaignGroupId: String!): Boolean! filterLandlines(id:String!): Campaign - bulkUpdateScript(organizationId:String!, findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateResult] + bulkUpdateScript(findAndReplace: BulkUpdateScriptInput!): [ScriptUpdateResult] deleteJob(campaignId:String!, id:String!): JobRequest copyCampaign(id: String!): Campaign copyCampaigns(sourceCampaignId: String!, quantity: Int!, targetOrgId: String): [Campaign!]! diff --git a/src/server/api/lib/bulk-script-editor.ts b/src/server/api/lib/bulk-script-editor.ts index 74cb75444..9246967a7 100644 --- a/src/server/api/lib/bulk-script-editor.ts +++ b/src/server/api/lib/bulk-script-editor.ts @@ -9,7 +9,7 @@ export const getStepsToUpdate = async ( trx: Knex.Transaction, findAndReplace: BulkUpdateScriptInput ) => { - const { searchString, campaignIds } = findAndReplace; + const { searchString, campaignIds, organizationId } = findAndReplace; const campaignsIds = campaignIds.map((cid: string) => parseInt(cid, 10)); // Using array_to_string is easier and faster than using unnest(script_options) (https://stackoverflow.com/a/7222285) @@ -25,7 +25,8 @@ export const getStepsToUpdate = async ( .join("campaign", "campaign_id", "campaign.id") .whereRaw("array_to_string(script_options, '||') like ?", [ `%${searchString}%` - ]); + ]) + .where({ organization_id: organizationId }); if (campaignsIds.length > 0) { interactionStepsToChangeQuery = interactionStepsToChangeQuery.whereIn( "campaign_id", diff --git a/src/server/api/root-mutations.ts b/src/server/api/root-mutations.ts index bf6fb28fe..b3790cd8a 100644 --- a/src/server/api/root-mutations.ts +++ b/src/server/api/root-mutations.ts @@ -1115,11 +1115,8 @@ const rootMutations = { return loaders.campaign.load(id); }, - bulkUpdateScript: async ( - _root, - { organizationId, findAndReplace }, - { user } - ) => { + bulkUpdateScript: async (_root, { findAndReplace }, { user }) => { + const { organizationId } = findAndReplace; await accessRequired(user, organizationId, "OWNER"); const scriptUpdatesResult = await r.knex.transaction(async (trx) => { diff --git a/src/server/api/root-resolvers.ts b/src/server/api/root-resolvers.ts index 17ac2699d..d740316bf 100644 --- a/src/server/api/root-resolvers.ts +++ b/src/server/api/root-resolvers.ts @@ -442,11 +442,8 @@ const rootResolvers = { nextCampaignId }; }, - bulkUpdateScriptChanges: async ( - _root, - { organizationId, findAndReplace }, - { user } - ) => { + bulkUpdateScriptChanges: async (_root, { findAndReplace }, { user }) => { + const { organizationId } = findAndReplace; await accessRequired(user, organizationId, "OWNER"); const steps = await r.knex.transaction((trx) => {