blob: 33c9224429291570a4cf9899acd1647217e9e5d6 [file] [log] [blame]
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +02001import '@material/web/button/outlined-button.js';
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +02002import '@material/web/textfield/filled-text-field.js';
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +02003import './ActionEditor.js';
4
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +02005import {css, html, LitElement, nothing} from 'lit';
6import {createRef, ref} from 'lit/directives/ref.js';
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +02007import {repeat} from 'lit/directives/repeat.js';
8
9import * as pb from '../../proto/main_pb.js';
Adrià Vilanova Martínez7f1e8ea2022-10-14 15:50:11 +020010import WorkflowsStorage from '../../workflowsStorage.js';
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020011
12export default class WFWorkflowEditor extends LitElement {
13 static properties = {
14 workflow: {type: Object},
15 readOnly: {type: Boolean},
16 };
17
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020018 static styles = css`
19 .name {
20 width: 100%;
21 margin-bottom: 20px;
22 }
23 `;
24
25 nameRef = createRef();
26
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020027 constructor() {
28 super();
29 this.workflow = new pb.workflows.Workflow();
30 this.readOnly = false;
31 }
32
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020033 renderName() {
34 return html`
35 <md-filled-text-field ${ref(this.nameRef)}
36 class="name"
37 placeholder="Untitled workflow"
38 value=${this.workflow.getName()}
39 required
40 @input=${this._nameChanged}>
41 </md-filled-text-field>
42 `;
43 }
44
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020045 renderActions() {
46 return repeat(this._actions(), (action, i) => html`
47 <wf-action-editor
48 .action=${action}
49 ?readOnly=${this.readOnly}
50 ?disableRemoveButton=${this._actions().length <= 1}
51 step=${i + 1}
52 @action-removed=${() => this._removeAction(i)}>
53 </wf-action-editor>
54 `);
55 }
56
57 renderAddActionBtn() {
58 if (this.readOnly) return nothing;
59 return html`
60 <md-outlined-button
61 icon="add"
62 label="Add another action"
63 @click=${this._addAction}>
64 </md-outlined-button>
65 `;
66 }
67
68 render() {
69 return [
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020070 this.renderName(),
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020071 this.renderActions(),
72 this.renderAddActionBtn(),
73 ];
74 }
75
Adrià Vilanova Martínez8803b6c2022-10-17 00:36:38 +020076 checkValidity() {
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020077 let allValid = true;
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020078
79 // Check the workflow name is set
80 allValid &&= this.nameRef.value.reportValidity();
81
82 // Check all the actions are well-formed
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +020083 const actionEditors = this.renderRoot.querySelectorAll('wf-action-editor');
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020084 for (const editor of actionEditors) allValid &&= editor.checkValidity();
85
Adrià Vilanova Martínez8803b6c2022-10-17 00:36:38 +020086 return allValid;
87 }
88
89 save(uuid) {
90 const allValid = this.checkValidity();
91
Adrià Vilanova Martínez7f1e8ea2022-10-14 15:50:11 +020092 // Save the workflow if the validation checks passed
Adrià Vilanova Martínez8803b6c2022-10-17 00:36:38 +020093 if (allValid) {
94 if (!uuid)
95 WorkflowsStorage.add(this.workflow);
96 else
97 WorkflowsStorage.update(uuid, this.workflow);
98 }
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +020099
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +0200100 return allValid;
101 }
102
103 _actions() {
104 return this.workflow.getActionsList();
105 }
106
Adrià Vilanova Martínezc5507dd2022-10-13 23:04:01 +0200107 _nameChanged() {
108 this.workflow.setName(this.nameRef.value.value);
109 this._dispatchUpdateEvent();
110 }
111
Adrià Vilanova Martínezf276ac72022-10-13 22:16:22 +0200112 _addAction() {
113 let action = new pb.workflows.Action();
114 let rAction = new pb.workflows.Action.ReplyWithCRAction();
115 action.setReplyWithCrAction(rAction);
116 this.workflow.addActions(action);
117 this._dispatchUpdateEvent();
118 }
119
120 _removeAction(index) {
121 let actions = this.workflow.getActionsList();
122 actions.splice(index, 1);
123 this.workflow.setActionsList(actions);
124 this._dispatchUpdateEvent();
125 }
126
127 _updateAction(index, action) {
128 let actions = this.workflow.getActionsList();
129 actions[index] = action;
130 this.workflow.setActionsList(actions);
131 this._dispatchUpdateEvent();
132 }
133
134 _dispatchUpdateEvent() {
135 // Request an update for this component
136 this.requestUpdate();
137
138 // Transmit to other components that the workflow has changed
139 const e = new Event('workflow-updated', {bubbles: true, composed: true});
140 this.renderRoot.dispatchEvent(e);
141 }
142}
143window.customElements.define('wf-workflow-editor', WFWorkflowEditor);