blob: 164d2265ec92eb19eef3d4db94b4e25537f721ef [file] [log] [blame]
Adrià Vilanova Martínez78dcfdf2024-02-26 02:02:22 +01001import {recursiveParentElement} from '../../../common/commonUtils.js';
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +02002import * as pb from '../../../workflows/proto/main_pb.js';
3
Adrià Vilanova Martínez78dcfdf2024-02-26 02:02:22 +01004import AttributeRunner from './actionRunners/attribute.js';
Adrià Vilanova Martínez6c4739a2022-11-07 00:11:53 +01005import ReadStateRunner from './actionRunners/readState.js';
Adrià Vilanova Martínez78dcfdf2024-02-26 02:02:22 +01006import CRRunner from './actionRunners/replyWithCR.js';
Adrià Vilanova Martínez41493f22022-11-06 22:38:21 +01007import Thread from './models/thread.js';
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +02008
9export default class WorkflowRunner {
10 constructor(workflow, updateCallback) {
11 this.workflow = workflow;
12 this._threads = [];
13 this._currentThreadIndex = 0;
14 this._currentActionIndex = 0;
15 // Can be 'waiting', 'running', 'error', 'finished'
16 this._status = 'waiting';
17 this._updateCallback = updateCallback;
18
19 // Initialize action runners:
Adrià Vilanova Martínez78dcfdf2024-02-26 02:02:22 +010020 this._AttributeRunner = new AttributeRunner();
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +020021 this._CRRunner = new CRRunner();
Adrià Vilanova Martínez6c4739a2022-11-07 00:11:53 +010022 this._ReadStateRunner = new ReadStateRunner();
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +020023 }
24
25 start() {
26 this._getSelectedThreads();
27 this.status = 'running';
28 this._runNextAction();
29 }
30
31 _getSelectedThreads() {
32 let threads = [];
33 const checkboxes = document.querySelectorAll(
34 '.thread-group material-checkbox[aria-checked="true"]');
35
36 for (const checkbox of checkboxes) {
37 const url = recursiveParentElement(checkbox, 'EC-THREAD-SUMMARY')
38 .querySelector('a.header-content')
39 .href;
Adrià Vilanova Martínez41493f22022-11-06 22:38:21 +010040 const thread = Thread.fromUrl(url);
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +020041 if (!thread) {
42 console.error('Couldn\'t parse URL ' + url);
43 continue;
44 }
45 threads.push(thread);
46 }
47
48 this.threads = threads;
49 }
50
51 _showError(err) {
52 console.warn(
53 `An error ocurred while executing action ${this.currentActionIndex}.`,
54 err);
55 this.status = 'error';
56 }
57
58 _runAction() {
59 switch (this._currentAction?.getActionCase?.()) {
Adrià Vilanova Martínez78dcfdf2024-02-26 02:02:22 +010060 case pb.workflows.Action.ActionCase.ATTRIBUTE_ACTION:
61 return this._AttributeRunner.execute(
62 this._currentAction?.getAttributeAction?.(), this._currentThread);
63
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +020064 case pb.workflows.Action.ActionCase.REPLY_WITH_CR_ACTION:
65 return this._CRRunner.execute(
66 this._currentAction?.getReplyWithCrAction?.(), this._currentThread);
67
Adrià Vilanova Martínez6c4739a2022-11-07 00:11:53 +010068 case pb.workflows.Action.ActionCase.MARK_AS_READ_ACTION:
69 return this._ReadStateRunner.execute(true, this._currentThread);
70
71 case pb.workflows.Action.ActionCase.MARK_AS_UNREAD_ACTION:
72 return this._ReadStateRunner.execute(false, this._currentThread);
73
Adrià Vilanova Martínez54964a52022-10-26 23:53:29 +020074 default:
75 return Promise.reject(new Error('This action isn\'t supported yet.'));
76 }
77 }
78
79 _runNextAction() {
80 if (this.status !== 'running')
81 return console.error(
82 'Trying to run next action with status ' + this.status + '.');
83
84 this._runAction()
85 .then(() => {
86 if (this._nextActionIfAvailable())
87 this._runNextAction();
88 else
89 this._finish();
90 })
91 .catch(err => this._showError(err));
92 }
93
94 _nextActionIfAvailable() {
95 if (this.currentActionIndex === this._actions.length - 1) {
96 if (this.currentThreadIndex === this.numThreads - 1) return false;
97
98 this.currentThreadIndex++;
99 this.currentActionIndex = 0;
100 return true;
101 }
102
103 this.currentActionIndex++;
104 return true;
105 }
106
107 _finish() {
108 this.status = 'finished';
109 }
110
111 get numThreads() {
112 return this.threads.length ?? 0;
113 }
114
115 get _actions() {
116 return this.workflow?.getActionsList?.();
117 }
118
119 get _currentAction() {
120 return this._actions?.[this.currentActionIndex];
121 }
122
123 get _currentThread() {
124 return this._threads?.[this.currentThreadIndex];
125 }
126
127 // Setters/getters for properties, which will update the UI when changed.
128 get threads() {
129 return this._threads;
130 }
131
132 set threads(value) {
133 this._threads = value;
134 this._updateCallback();
135 }
136
137 get currentThreadIndex() {
138 return this._currentThreadIndex;
139 }
140
141 set currentThreadIndex(value) {
142 this._currentThreadIndex = value;
143 this._updateCallback();
144 }
145
146 get currentActionIndex() {
147 return this._currentActionIndex;
148 }
149
150 set currentActionIndex(value) {
151 this._currentActionIndex = value;
152 this._updateCallback();
153 }
154
155 get status() {
156 return this._status;
157 }
158
159 set status(value) {
160 this._status = value;
161 this._updateCallback();
162 }
163}