blob: 8172b6203c0ea91e32251ab4e061bb1e77b7377a [file] [log] [blame]
Adrià Vilanova Martíneze0d65f22022-11-06 18:49:35 +01001import {waitFor} from 'poll-until-promise';
2
3import {recursiveParentElement} from '../../../common/commonUtils.js';
4import {injectStylesheet} from '../../../common/contentScriptsUtils.js';
5import {isOptionEnabled} from '../../../common/optionsUtils.js';
6
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);
19 if (!searchParams.has(kImportParam)) return;
20
21 this.selectedId = searchParams.get(kSelectedIdParam);
22
23 this.lastCRsList = {
24 body: {},
25 id: -1,
26 duplicateNames: new Set(),
27 };
28
29 this.setUpHandler();
30 this.addCustomStyles();
31 }
32
33 setUpHandler() {
34 window.addEventListener(kListCannedResponsesResponse, e => {
35 if (e.detail.id < this.lastCRsList.id) return;
36
37 // Look if there are duplicate names
38 const crs = e.detail.body?.['1'] ?? [];
39 const names = crs.map(cr => cr?.['7']).slice().sort();
40 let duplicateNames = new Set();
41 for (let i = 1; i < names.length; i++)
42 if (names[i - 1] == names[i]) duplicateNames.add(names[i]);
43
44 this.lastCRsList = {
45 body: e.detail.body,
46 id: e.detail.id,
47 duplicateNames,
48 };
49 });
50 }
51
52 addCustomStyles() {
53 injectStylesheet(chrome.runtime.getURL('css/workflow_import.css'));
54 }
55
56 addButton(tags) {
57 const cr = recursiveParentElement(tags, 'EC-CANNED-RESPONSE-ROW');
58 if (!cr) return;
59
60 const name = cr.querySelector('.text .name').textContent;
61 if (!name) return;
62
63 const toolbar = cr.querySelector('.action .toolbar');
64 if (!toolbar) return console.error(`Can't find toolbar.`);
65
66 // If it has already been injected, exit.
67 if (toolbar.querySelector('twpt-cr-import-button')) return;
68
69 waitFor(() => {
70 if (this.lastCRsList.id != -1) return Promise.resolve(this.lastCRsList);
71 return Promise.reject(new Error('Didn\'t receive canned responses list'));
72 }, {
73 interval: 500,
74 timeout: 15 * 1000,
75 }).then(crs => {
76 // If another CR has the same name, there's no easy way to distinguish
77 // them, so don't inject the button.
78 if (crs.duplicateNames.has(name)) {
79 console.info(
80 'CR "' + name +
81 '" is duplicate, so skipping the injection of the button.');
82 return;
83 }
84
85 for (const cr of (crs.body?.[1] ?? [])) {
86 if (cr[7] == name) {
87 const id = cr?.[1]?.[1];
88 if (!id) {
89 console.error('Can\'t find ID for canned response', cr);
90 break;
91 }
92
93 const button = document.createElement('twpt-cr-import-button');
94 button.setAttribute('cannedResponseId', id);
95 if (this.selectedId == id) button.setAttribute('selected', '');
96 toolbar.prepend(button);
97 break;
98 }
99 }
100 });
101 }
102
103 addButtonIfEnabled(tags) {
104 isOptionEnabled('workflows').then(isEnabled => {
105 if (isEnabled) this.addButton(tags);
106 });
107 }
108}