feat(workflows): add "attribute action" action
This action lets users perform several actions on threads, such as
(un)lock, (un)set as trending, (un)pin, set as non-issue, obsolete, etc.
The action selector shows the action with the codename it has in the
Protobuf enum. We will show a friendly string when we localize the
feature.
Bug: twpowertools:74
Change-Id: I95f9f1904ffe559c92a786cbdb327613c8ca32ca
diff --git a/src/workflows/manager/components/ActionEditor.js b/src/workflows/manager/components/ActionEditor.js
index 9a57509..cdcb85a 100644
--- a/src/workflows/manager/components/ActionEditor.js
+++ b/src/workflows/manager/components/ActionEditor.js
@@ -1,5 +1,5 @@
+import './actions/Attribute.js';
import './actions/ReplyWithCR.js';
-
import '@material/mwc-circular-progress/mwc-circular-progress.js';
import {html, LitElement, nothing} from 'lit';
@@ -61,6 +61,14 @@
</wf-action-reply-with-cr>
`;
+ case pb.workflows.Action.ActionCase.ATTRIBUTE_ACTION:
+ return html`
+ <wf-action-attribute
+ ?readOnly=${this.readOnly}
+ .action=${this.action.getAttributeAction()}>
+ </wf-action-attribute>
+ `;
+
case pb.workflows.Action.ActionCase.MARK_AS_READ_ACTION:
case pb.workflows.Action.ActionCase.MARK_AS_UNREAD_ACTION:
return nothing;
@@ -216,6 +224,9 @@
case pb.workflows.Action.ActionCase.REPLY_WITH_CR_ACTION:
return this.renderRoot.querySelector('wf-action-reply-with-cr');
+ case pb.workflows.Action.ActionCase.ATTRIBUTE_ACTION:
+ return this.renderRoot.querySelector('wf-action-attribute');
+
default:
return null;
}
diff --git a/src/workflows/manager/components/actions/Attribute.js b/src/workflows/manager/components/actions/Attribute.js
new file mode 100644
index 0000000..150e7da
--- /dev/null
+++ b/src/workflows/manager/components/actions/Attribute.js
@@ -0,0 +1,89 @@
+import '@material/web/select/outlined-select.js';
+import '@material/web/select/select-option.js';
+
+import {html, LitElement} from 'lit';
+import {createRef, ref} from 'lit/directives/ref.js';
+
+import {SHARED_MD3_STYLES} from '../../../../common/styles/md3.js';
+import * as pb from '../../../proto/main_pb.js';
+
+import {FORM_STYLES} from './common.js';
+
+const kHiddenActions = [
+ pb.workflows.Action.AttributeAction.AttributeAction.AA_NONE,
+ pb.workflows.Action.AttributeAction.AttributeAction.AA_SOFT_LOCK,
+ pb.workflows.Action.AttributeAction.AttributeAction.AA_UNSOFT_LOCK,
+];
+
+export default class WFActionAttribute extends LitElement {
+ static properties = {
+ action: {type: Object},
+ readOnly: {type: Boolean},
+ };
+
+ static styles = [
+ SHARED_MD3_STYLES,
+ FORM_STYLES,
+ ];
+
+ attributeActionRef = createRef();
+
+ constructor() {
+ super();
+ this.action = new pb.workflows.Action.AttributeAction;
+ }
+
+ render() {
+ return html`
+ <div class="form-line">
+ <md-outlined-select ${ref(this.attributeActionRef)}
+ required
+ label="Action"
+ value=${this.action}
+ ?disabled=${this.readOnly}
+ @change=${this._attributeActionChanged}>
+ ${this.renderAttributeActions()}
+ </md-outlined-select>
+ </div>
+ `;
+ }
+
+ renderAttributeActions() {
+ const attributeActions =
+ Object.entries(pb.workflows.Action.AttributeAction.AttributeAction);
+ return attributeActions.filter(([, id]) => !kHiddenActions.includes(id))
+ .map(([actionCodename, id]) => html`
+ <md-select-option value=${id}>
+ <div slot="headline">${actionCodename}</div>
+ </md-select-option>
+ `);
+ }
+
+ checkValidity() {
+ return this.attributeActionRef.value.reportValidity();
+ }
+
+ _dispatchUpdateEvent() {
+ // Request an update for this component
+ this.requestUpdate();
+
+ // Transmit to other components that the action has changed
+ const e =
+ new Event('attribute-action-updated', {bubbles: true, composed: true});
+ this.renderRoot.dispatchEvent(e);
+ }
+
+ _attributeActionChanged() {
+ this.attributeAction = this.attributeActionRef.value.value;
+ }
+
+ get attributeAction() {
+ return this.action.getAttributeAction();
+ }
+
+ set attributeAction(value) {
+ this.action.setAttributeAction(value);
+ this._dispatchUpdateEvent();
+ }
+}
+window.customElements.define('wf-action-attribute', WFActionAttribute);
diff --git a/src/workflows/manager/components/actions/ReplyWithCR.js b/src/workflows/manager/components/actions/ReplyWithCR.js
index 40a6b9c..e97f6f4 100644
--- a/src/workflows/manager/components/actions/ReplyWithCR.js
+++ b/src/workflows/manager/components/actions/ReplyWithCR.js
@@ -8,6 +8,7 @@
import {SHARED_MD3_STYLES} from '../../../../common/styles/md3.js';
import * as pb from '../../../proto/main_pb.js';
+import { FORM_STYLES } from './common.js';
export default class WFActionReplyWithCR extends LitElement {
static properties = {
@@ -18,15 +19,8 @@
static styles = [
SHARED_MD3_STYLES,
+ FORM_STYLES,
css`
- .form-line {
- display: flex;
- flex-direction: row;
- align-items: center;
- margin-block: 1em;
- gap: .5rem;
- }
-
.select-cr-btn {
--md-outlined-button-icon-size: 24px;
}
diff --git a/src/workflows/manager/components/actions/common.js b/src/workflows/manager/components/actions/common.js
new file mode 100644
index 0000000..3d5be56
--- /dev/null
+++ b/src/workflows/manager/components/actions/common.js
@@ -0,0 +1,11 @@
+import {css} from 'lit';
+
+export const FORM_STYLES = css`
+ .form-line {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ margin-block: 1em;
+ gap: .5rem;
+ }
+`;