Skip to content

Commit

Permalink
feat(alerts): ajout d'un feature de notification pour les alertes de …
Browse files Browse the repository at this point in the history
…la dares (#1004)

* fix: alert

* fix: alert

* fix: alert

* feat: ajout de la 1979

* fix: alert

* fix: autoscroll
  • Loading branch information
maxgfr authored Sep 22, 2023
1 parent c55bd4c commit 530043d
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 5 deletions.
31 changes: 30 additions & 1 deletion shared/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ export type AlertInfo = { id: string };
export type AlertChanges =
| DilaAlertChanges
| TravailDataAlertChanges
| VddAlertChanges;
| VddAlertChanges
| DaresAlertChanges;

/** Dila alert changes */
export type DilaAlertChanges = DilaChanges & {
Expand Down Expand Up @@ -382,6 +383,34 @@ export type VddAlertChanges = VddChanges & {
date: Date;
};

export type DaresAlertChanges = {
type: "dares";
title: string;
ref: string;
date: Date;
modified: [];
added: {
name: string;
num: number;
}[];
removed: {
name: string;
num: number;
}[];
documents: [];
};

export type DaresAlert = {
id: string;
info: {
id: string | number; // idcc number
};
status: "doing" | "done" | "rejected" | "todo";
repository: "dares";
ref: string;
changes: DaresAlertChanges;
};

export type VddChanges = {
modified: FicheVddInfoWithDiff[];
removed: FicheVddInfo[];
Expand Down
2 changes: 1 addition & 1 deletion targets/alert-cli/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const config = {
preset: "ts-jest/presets/js-with-ts-esm",
testMatch: ["**/__tests__/**/?(*.)+(spec|test).+(ts|tsx|js)"],
transformIgnorePatterns: [
"node_modules/(?!(unist-util-select|zwitch|unist-util-is)/)",
"node_modules/(?!(unist-util-select|zwitch|unist-util-is|axios)/)",
],
};

Expand Down
2 changes: 2 additions & 0 deletions targets/alert-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"@socialgouv/cdtn-slugify": "4.52.1",
"@socialgouv/cdtn-sources": "4.52.1",
"@socialgouv/dila-api-client": "1.2.4",
"axios": "^1.5.0",
"diff": "^5.1.0",
"memoizee": "0.4.15",
"node-xlsx": "^0.23.0",
"p-map": "4",
"semver": "7.3.5",
"simple-git": "^3.19.1",
Expand Down
34 changes: 34 additions & 0 deletions targets/alert-cli/src/dares/__tests__/scrapping.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import axios from "axios";
import { extractXlsxFromUrl } from "../scrapping";

jest.mock("axios");

describe("extractXlsxFromUrl", () => {
it("should extract xlsx file from url", async () => {
const url = "https://example.com/files";
const html = `
<html>
<body>
<a href="file1.xlsx">File 1</a>
<a href="file2.xlsx">File 2</a>
</body>
</html>
`;
(axios.get as jest.Mock).mockResolvedValueOnce({ data: html });
const result = await extractXlsxFromUrl(url);
expect(result).toBe("file1.xlsx");
});

it("should throw error if no xlsx file found", async () => {
const url = "https://example.com/files";
const html = `
<html>
<body>
<a href="file1.pdf">File 1</a>
</body>
</html>
`;
(axios.get as jest.Mock).mockResolvedValueOnce({ data: html });
await expect(extractXlsxFromUrl(url)).rejects.toThrow("No xlsx file found");
});
});
4 changes: 4 additions & 0 deletions targets/alert-cli/src/dares/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const URL_SCRAPING =
"https://code.travail.gouv.fr/fiche-ministere-travail/conventions-collectives-nomenclatures";
export const URL_KALI =
"https://raw.githubusercontent.com/SocialGouv/kali-data/master/data/index.json";
46 changes: 46 additions & 0 deletions targets/alert-cli/src/dares/difference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import xlsx from "node-xlsx";
import { Diff, Agreement } from "./types";
import fs from "fs";

export function getDifferenceBetweenIndexAndDares(
pathDares: string,
pathIndex: string
): Diff {
const workSheetsFromFile = xlsx.parse(pathDares);

const supportedCcXlsx: Agreement[] = [];

workSheetsFromFile[0].data.forEach((row: string[]) => {
const ccNumber = parseInt(row[0]);
const ccName = row[1];
if (ccNumber && ccName) {
const ccNameWithoutParenthesis = ccName
.replace(/\(.*annexée.*\)/gi, "")
.trim();
supportedCcXlsx.push({
name: ccNameWithoutParenthesis,
num: ccNumber,
});
}
});

const dataJson = JSON.parse(fs.readFileSync(pathIndex, "utf8"));

const supportedCcIndexJson: Agreement[] = dataJson.map((cc: any) => {
return {
name: cc.title,
num: cc.num,
};
});

const missingAgreementsFromDares: Agreement[] = supportedCcXlsx.filter(
(ccIndex) =>
!supportedCcIndexJson.find((ccXlsx) => ccXlsx.num === ccIndex.num)
);

const exceedingAgreementsFromKali = supportedCcIndexJson.filter(
(ccXlsx) => !supportedCcXlsx.find((ccIndex) => ccIndex.num === ccXlsx.num)
);

return { missingAgreementsFromDares, exceedingAgreementsFromKali };
}
21 changes: 21 additions & 0 deletions targets/alert-cli/src/dares/download.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import axios from "axios";
import fs from "fs";
import os from "os";
import path from "path";

export async function downloadFileInTempFolder(
url: string,
nameOfFile: string
): Promise<string> {
const tempDir = os.tmpdir();
const filePath = path.join(tempDir, nameOfFile);

const response = await axios.get(url, { responseType: "stream" });
const writer = fs.createWriteStream(filePath);
response.data.pipe(writer);

return new Promise((resolve, reject) => {
writer.on("finish", () => resolve(filePath));
writer.on("error", reject);
});
}
13 changes: 13 additions & 0 deletions targets/alert-cli/src/dares/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { URL_KALI, URL_SCRAPING } from "./config";
import { getDifferenceBetweenIndexAndDares } from "./difference";
import { downloadFileInTempFolder } from "./download";
import { saveDiff } from "./save";
import { extractXlsxFromUrl } from "./scrapping";

export const runDares = async () => {
const xlsxUrl = await extractXlsxFromUrl(URL_SCRAPING);
const xlsxPath = await downloadFileInTempFolder(xlsxUrl, "dares.xlsx");
const indexPath = await downloadFileInTempFolder(URL_KALI, "index.json");
const diff = await getDifferenceBetweenIndexAndDares(xlsxPath, indexPath);
await saveDiff(diff);
};
70 changes: 70 additions & 0 deletions targets/alert-cli/src/dares/save.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { AlertRepository } from "../repositories/AlertRepository";
import { DaresAlertInsert, Diff } from "./types";
import { client } from "@shared/graphql-client";

export const saveDiff = async (diff: Diff) => {
const alertRepository = new AlertRepository(client);

const alertsRemovedToSave: DaresAlertInsert[] =
diff.exceedingAgreementsFromKali.map((agreement) => ({
info: {
id: agreement.num,
},
status: "todo",
repository: "dares",
ref: "v0",
changes: {
type: "dares",
title: agreement.name,
ref: agreement.num.toString(),
date: new Date(),
modified: [],
removed: [
{
name: agreement.name,
num: agreement.num,
},
],
added: [],
documents: [],
},
}));

const alertsAddedToSave: DaresAlertInsert[] =
diff.missingAgreementsFromDares.map((agreement) => ({
info: {
id: agreement.num,
},
status: "todo",
repository: "dares",
ref: "v0",
changes: {
type: "dares",
title: agreement.name,
ref: agreement.num.toString(),
date: new Date(),
modified: [],
added: [
{
name: agreement.name,
num: agreement.num,
},
],
removed: [],
documents: [],
},
}));

const alertsToSave = [...alertsAddedToSave, ...alertsRemovedToSave];

const inserts = await Promise.allSettled(
alertsToSave.map((alert) => alertRepository.saveAlertDares(alert))
);

inserts.forEach((insert) => {
if (insert.status === "fulfilled") {
const { ref, repository: repo, info } = insert.value;
console.log(`insert alert for ${ref} on ${repo} (${info.id})`);
}
});
};
12 changes: 12 additions & 0 deletions targets/alert-cli/src/dares/scrapping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import axios from "axios";

export const extractXlsxFromUrl = async (url: string) => {
const response = await axios.get(url);
const html = response.data;
const regex = /href="([^"]*\.xlsx)"/g;
const match = regex.exec(html);
if (!match) {
throw new Error("No xlsx file found");
}
return match[1];
};
13 changes: 13 additions & 0 deletions targets/alert-cli/src/dares/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DaresAlert } from "@shared/types";

export interface Diff {
missingAgreementsFromDares: Agreement[];
exceedingAgreementsFromKali: Agreement[];
}

export interface Agreement {
name: string;
num: number;
}

export type DaresAlertInsert = Omit<DaresAlert, "id">;
2 changes: 2 additions & 0 deletions targets/alert-cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SourcesRepository } from "./repositories/SourcesRepository";
import { AlertRepository } from "./repositories/AlertRepository";
import { AlertDetector } from "./diff";
import { FicheSPRepository } from "./repositories/FicheSPRepository";
import { runDares } from "./dares";

export * from "./types";

Expand Down Expand Up @@ -51,6 +52,7 @@ export async function run(
}

async function main() {
await runDares();
const githubToken = process.env.GITHUB_TOKEN;
if (!githubToken) {
throw new Error("GITHUB_TOKEN is not defined");
Expand Down
16 changes: 15 additions & 1 deletion targets/alert-cli/src/repositories/AlertRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Client } from "@urql/core/dist/types/client";
import { AlertChanges, AlertInfo, HasuraAlert } from "@shared/types";
import { batchPromises } from "../batchPromises";
import { DaresAlertInsert } from "../dares/types";

const insertAlertsMutation = `
mutation insert_alert($alert: alerts_insert_input!) {
Expand All @@ -9,7 +10,7 @@ mutation insert_alert($alert: alerts_insert_input!) {
update_columns: [changes]
}) {
repository,
ref
ref,
info
}
}
Expand All @@ -30,6 +31,19 @@ export class AlertRepository {
this.client = client;
}

async saveAlertDares(data: DaresAlertInsert) {
const result = await this.client
.mutation<InsertAlertData>(insertAlertsMutation, {
alert: data,
})
.toPromise();
if (result.error || !result.data) {
console.error(result.error);
throw new Error("insertAlert");
}
return result.data.alert;
}

async saveAlertChanges(repository: string, alertChanges: AlertChanges[]) {
const inserts = await batchPromises(
alertChanges,
Expand Down
3 changes: 2 additions & 1 deletion targets/alert-cli/src/repositories/SourcesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export class SourcesRepository {
console.error(result.error);
throw new Error("getSources");
}
return result.data.sources;
const sources = result.data.sources;
return sources.filter((source) => source.repository !== "dares");
}

async updateSource(repository: string, tag: string): Promise<Source> {
Expand Down
Loading

0 comments on commit 530043d

Please sign in to comment.