blob: 09ffc0a93ea214b818c28d0cae59c4ac9174c278 [file] [log] [blame]
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +01001import {waitFor} from 'poll-until-promise';
2
Adrià Vilanova Martínezc78c3ad2024-05-18 00:35:51 +02003import {recursiveParentElement} from '../../../../common/commonUtils.js';
Adrià Vilanova Martínezd7951b22024-05-25 22:13:32 +02004import {injectStylesheet} from '../../../../common/contentScriptsUtils';
Adrià Vilanova Martínezb523be92024-05-25 19:14:19 +02005import {isOptionEnabled} from '../../../../common/options/optionsUtils.js';
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +01006
7const kListCannedResponsesResponse = 'TWPT_ListCannedResponsesResponse';
8
9const kImportParam = 'TWPTImportToWorkflow';
10const kSelectedIdParam = 'TWPTSelectedId';
11
12// Class which is used to inject a "select" button in the CRs list when loading
13// the canned response list for this purpose from the workflows manager.
14export default class WorkflowsImport {
15 constructor() {
16 // Only set this class up if the Community Console was opened with the
17 // purpose of importing CRs to the workflow manager.
18 const searchParams = new URLSearchParams(document.location.search);
Adrià Vilanova Martínez17a98e82024-06-22 16:26:40 +020019 this.isSetUp = searchParams.has(kImportParam);
20 if (!this.isSetUp) return;
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +010021
22 this.selectedId = searchParams.get(kSelectedIdParam);
23
24 this.lastCRsList = {
25 body: {},
26 id: -1,
27 duplicateNames: new Set(),
28 };
29
30 this.setUpHandler();
31 this.addCustomStyles();
32 }
33
34 setUpHandler() {
35 window.addEventListener(kListCannedResponsesResponse, e => {
36 if (e.detail.id < this.lastCRsList.id) return;
37
38 // Look if there are duplicate names
39 const crs = e.detail.body?.['1'] ?? [];
40 const names = crs.map(cr => cr?.['7']).slice().sort();
41 let duplicateNames = new Set();
42 for (let i = 1; i < names.length; i++)
43 if (names[i - 1] == names[i]) duplicateNames.add(names[i]);
44
45 this.lastCRsList = {
46 body: e.detail.body,
47 id: e.detail.id,
48 duplicateNames,
49 };
50 });
51 }
52
53 addCustomStyles() {
54 injectStylesheet(chrome.runtime.getURL('css/workflow_import.css'));
55 }
56
57 addButton(tags) {
58 const cr = recursiveParentElement(tags, 'EC-CANNED-RESPONSE-ROW');
59 if (!cr) return;
60
61 const name = cr.querySelector('.text .name').textContent;
62 if (!name) return;
63
64 const toolbar = cr.querySelector('.action .toolbar');
65 if (!toolbar) return console.error(`Can't find toolbar.`);
66
67 // If it has already been injected, exit.
68 if (toolbar.querySelector('twpt-cr-import-button')) return;
69
70 waitFor(() => {
71 if (this.lastCRsList.id != -1) return Promise.resolve(this.lastCRsList);
72 return Promise.reject(new Error('Didn\'t receive canned responses list'));
73 }, {
74 interval: 500,
75 timeout: 15 * 1000,
76 }).then(crs => {
77 // If another CR has the same name, there's no easy way to distinguish
78 // them, so don't inject the button.
79 if (crs.duplicateNames.has(name)) {
Adrià Vilanova Martínez5b987932023-11-16 02:18:44 +010080 console.warning(
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +010081 'CR "' + name +
82 '" is duplicate, so skipping the injection of the button.');
83 return;
84 }
85
86 for (const cr of (crs.body?.[1] ?? [])) {
87 if (cr[7] == name) {
88 const id = cr?.[1]?.[1];
89 if (!id) {
90 console.error('Can\'t find ID for canned response', cr);
91 break;
92 }
93
94 const button = document.createElement('twpt-cr-import-button');
95 button.setAttribute('cannedResponseId', id);
96 if (this.selectedId == id) button.setAttribute('selected', '');
97 toolbar.prepend(button);
98 break;
99 }
100 }
101 });
102 }
103
Adrià Vilanova Martínez17a98e82024-06-22 16:26:40 +0200104 addButtonIfApplicable(tags) {
105 if (!this.isSetUp) return;
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +0100106 isOptionEnabled('workflows').then(isEnabled => {
107 if (isEnabled) this.addButton(tags);
108 });
109 }
110}