diff --git a/src/features/webhookTrigger/index.ts b/src/features/webhookTrigger/index.ts index c9d026fd4..d12aa6269 100644 --- a/src/features/webhookTrigger/index.ts +++ b/src/features/webhookTrigger/index.ts @@ -15,7 +15,7 @@ export class WebhookTrigger data: Extract["data"]; }) { if (type === "status_change") { - this.webhookUrl = process.env.STATUS_CHANGE_WEBHOOK_URL || ""; + this.webhookUrl = process.env.STATUS_CHANGE_WEBHOOK || ""; } else if (type === "campaign_created") { this.webhookUrl = process.env.CAMPAIGN_CREATION_WEBHOOK || ""; } else { @@ -26,9 +26,14 @@ export class WebhookTrigger } async trigger() { - await axios.post(this.webhookUrl, { - ...this.data, - environment: process.env.ENVIROMENT, - }); + try { + await axios.post(this.webhookUrl, { + ...this.data, + environment: process.env.ENVIROMENT, + }); + } catch (e) { + console.error("Error triggering webhook", e); + throw e; + } } } diff --git a/src/features/wp/WordpressJsonApiTrigger/index.ts b/src/features/wp/WordpressJsonApiTrigger/index.ts index a5a94e142..0458b1cb8 100644 --- a/src/features/wp/WordpressJsonApiTrigger/index.ts +++ b/src/features/wp/WordpressJsonApiTrigger/index.ts @@ -22,14 +22,19 @@ class WordpressJsonApiTrigger { } private async postToWordpress(url: string) { - await axios({ - method: "GET", - url: `${process.env.WORDPRESS_API_URL}/${url}`, - headers: { - "User-Agent": "Tryber API", - "Content-Type": "application/json", - }, - }); + try { + await axios({ + method: "GET", + url: `${process.env.WORDPRESS_API_URL}/${url}`, + headers: { + "User-Agent": "Tryber API", + "Content-Type": "application/json", + }, + }); + } catch (e) { + console.error("Error triggering wp", e); + throw e; + } } } diff --git a/src/reference/openapi.yml b/src/reference/openapi.yml index 17bcc15c9..16a9bc1f8 100644 --- a/src/reference/openapi.yml +++ b/src/reference/openapi.yml @@ -1870,18 +1870,27 @@ paths: application/json: schema: type: object + required: + - items properties: items: type: array items: type: object + required: + - id + - name + - time + - tester + - cluster + - media properties: id: type: integer name: type: string time: - type: integer + type: number tester: type: object required: @@ -1915,15 +1924,6 @@ paths: type: string streamUrl: type: string - required: - - id - - name - - time - - tester - - cluster - - media - required: - - items examples: 3-observations: value: @@ -2864,9 +2864,9 @@ paths: id: type: integer start: - type: integer + type: number end: - type: integer + type: number mediaId: type: integer url: @@ -3321,9 +3321,9 @@ paths: id: type: integer start: - type: integer + type: number end: - type: integer + type: number mediaId: type: integer description: @@ -9755,10 +9755,29 @@ paths: properties: id: type: integer + message: + type: string + x-stoplight: + id: 8a0ic1hhs5mpz + enum: + - HOOK_FAILED + required: + - id examples: Example 1: value: id: 1 + '206': + description: Partial Content + content: + application/json: + schema: + type: object + properties: + id: + type: integer + x-stoplight: + id: y5n0dny2hhlc8 security: - JWT: [] requestBody: @@ -9782,6 +9801,10 @@ paths: type: integer testers: type: integer + campaign: + type: integer + x-stoplight: + id: 8os8pe07l1htz '/dossiers/{campaign}': parameters: - name: campaign diff --git a/src/routes/campaigns/campaignId/observations/_get/index.spec.ts b/src/routes/campaigns/campaignId/observations/_get/index.spec.ts index 5814a9dd0..eb8dca02a 100644 --- a/src/routes/campaigns/campaignId/observations/_get/index.spec.ts +++ b/src/routes/campaigns/campaignId/observations/_get/index.spec.ts @@ -47,7 +47,7 @@ beforeAll(async () => { id: 1, media_id: 1, name: "Observation1 name", - video_ts: 59, + video_ts: 59.5232, description: "Observation1 description", ux_note: "Observation1 ux_notes", }, @@ -55,7 +55,7 @@ beforeAll(async () => { id: 2, media_id: 2, name: "Observation2 name", - video_ts: 59, + video_ts: 59.5658, description: "Observation2 description", ux_note: "Observation2 ux_notes", }, @@ -63,7 +63,7 @@ beforeAll(async () => { id: 3, media_id: 3, name: "Observation2 name", - video_ts: 59, + video_ts: 59.545122, description: "Observation2 description", ux_note: "Observation2 ux_notes", }, @@ -250,7 +250,7 @@ describe("GET /campaigns/:campaignId/observations", () => { expect(response.body.items).toEqual( expect.arrayContaining([ expect.objectContaining({ - time: 59, + time: 59.5, }), ]) ); diff --git a/src/routes/campaigns/campaignId/observations/_get/index.ts b/src/routes/campaigns/campaignId/observations/_get/index.ts index 9a7dc146a..601fbdfa5 100644 --- a/src/routes/campaigns/campaignId/observations/_get/index.ts +++ b/src/routes/campaigns/campaignId/observations/_get/index.ts @@ -99,7 +99,7 @@ export default class SingleCampaignRoute extends CampaignRoute<{ results.push({ id: observation.id, name: observation.name, - time: observation.time, + time: Number(observation.time.toFixed(1)), cluster: { id: observation.cluster_id, name: observation.cluster_title, diff --git a/src/routes/dossiers/_post/index.ts b/src/routes/dossiers/_post/index.ts index a530d0c7d..93e2efd4c 100644 --- a/src/routes/dossiers/_post/index.ts +++ b/src/routes/dossiers/_post/index.ts @@ -141,19 +141,71 @@ export default class RouteItem extends AdminRoute<{ campaignId, }, }); - await webhook.trigger(); - this.setSuccess(201, { - id: campaignId, - }); + try { + await webhook.trigger(); + this.setSuccess(201, { + id: campaignId, + }); + } catch (e) { + this.setSuccess(201, { + id: campaignId, + message: "HOOK_FAILED", + }); + } } catch (e) { this.setError(500, e as OpenapiError); } } + private async getCampaignToDuplicate() { + const { duplicate } = this.getBody(); + if (!duplicate || !duplicate.campaign) return; + + const campaign = await tryber.tables.WpAppqEvdCampaign.do() + .select( + "id", + "desired_number_of_testers", + "min_allowed_media", + "cust_bug_vis", + "campaign_type", + "campaign_pts" + ) + .where("id", duplicate.campaign) + .first(); + + return campaign; + } + + private async duplicateMeta({ + campaignId, + campaignToDuplicate, + }: { + campaignId: number; + campaignToDuplicate: number; + }) { + const meta = await tryber.tables.WpAppqCpMeta.do() + .select() + .where("cp_id", campaignToDuplicate); + + if (meta.length) { + await tryber.tables.WpAppqCpMeta.do().insert( + meta.map((metaItem) => { + const { meta_id, ...rest } = metaItem; + return { + ...rest, + cp_id: campaignId, + }; + }) + ); + } + } + private async createCampaign() { const { os, form_factor } = await this.getDevices(); + const campaignToDuplicate = await this.getCampaignToDuplicate(); + const results = await tryber.tables.WpAppqEvdCampaign.do() .insert({ title: this.getBody().title.tester, @@ -171,11 +223,29 @@ export default class RouteItem extends AdminRoute<{ customer_title: this.getBody().title.customer, os: os.join(","), form_factor: form_factor.join(","), + base_bug_internal_id: "UG", + ...(campaignToDuplicate + ? { + desired_number_of_testers: + campaignToDuplicate.desired_number_of_testers, + min_allowed_media: campaignToDuplicate.min_allowed_media, + cust_bug_vis: campaignToDuplicate.cust_bug_vis, + campaign_type: campaignToDuplicate.campaign_type, + campaign_pts: campaignToDuplicate.campaign_pts, + } + : {}), }) .returning("id"); const campaignId = results[0].id ?? results[0]; + if (campaignToDuplicate) { + await this.duplicateMeta({ + campaignId, + campaignToDuplicate: campaignToDuplicate.id, + }); + } + const dossier = await tryber.tables.CampaignDossierData.do() .insert({ campaign_id: campaignId, diff --git a/src/schema.ts b/src/schema.ts index f2ad1ddae..9ad5667f8 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -4105,6 +4105,16 @@ export interface operations { responses: { /** Created */ 201: { + content: { + "application/json": { + id: number; + /** @enum {string} */ + message?: "HOOK_FAILED"; + }; + }; + }; + /** Partial Content */ + 206: { content: { "application/json": { id?: number; @@ -4121,6 +4131,7 @@ export interface operations { mailMerges?: number; pages?: number; testers?: number; + campaign?: number; }; }; };