fix(workflowengine): require a web component as operation plugin

solves an incompatibility issue when the providing app registers their code
from an incompatible nextcloud-vue version.

Also changes and clarifies WorkflowEngine API. This is necessary to stay
compatible with the original way, but also promotes usage of the originally
declared but never used "component" attribute on registration.

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
pull/50783/head
Arthur Schiwon 2025-02-12 21:11:47 +07:00
parent 12d32ee2ea
commit 96bd54b3ed
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
3 changed files with 40 additions and 4 deletions

@ -29,8 +29,13 @@
<div class="flow-icon icon-confirm" />
<div class="action">
<Operation :operation="operation" :colored="false">
<component :is="operation.element"
v-if="operation.element"
ref="operationComponent"
:model-value="inputValue"
@update:model-value="updateOperationByEvent" />
<component :is="operation.options"
v-if="operation.options"
v-else-if="operation.options"
v-model="rule.operation"
@input="updateOperation" />
</Operation>
@ -95,9 +100,14 @@ export default {
error: null,
dirty: this.rule.id < 0,
originalRule: null,
element: null,
inputValue: '',
}
},
computed: {
/**
* @return {OperatorPlugin}
*/
operation() {
return this.$store.getters.getOperationForRule(this.rule)
},
@ -123,11 +133,24 @@ export default {
},
mounted() {
this.originalRule = JSON.parse(JSON.stringify(this.rule))
if (this.operation?.element) {
this.$refs.operationComponent.value = this.rule.operation
} else if (this.operation?.options) {
// keeping this in an else for apps that try to be backwards compatible and may ship both
// to be removed in 03/2028
console.warn('Developer warning: `OperatorPlugin.options` is deprecated. Use `OperatorPlugin.element` instead.')
}
},
methods: {
async updateOperation(operation) {
this.$set(this.rule, 'operation', operation)
await this.updateRule()
this.updateRule()
},
async updateOperationByEvent(event) {
this.inputValue = event.detail[0]
this.$set(this.rule, 'operation', event.detail[0])
this.updateRule()
},
validate(/* state */) {
this.error = null
@ -164,6 +187,7 @@ export default {
if (this.rule.id < 0) {
this.$store.dispatch('removeRule', this.rule)
} else {
this.inputValue = this.originalRule.operation
this.$store.dispatch('updateRule', this.originalRule)
this.originalRule = JSON.parse(JSON.stringify(this.rule))
this.dirty = false

@ -127,6 +127,10 @@ const store = new Store({
return rule1.id - rule2.id || rule2.class - rule1.class
})
},
/**
* @param state
* @return {OperatorPlugin}
*/
getOperationForRule(state) {
return (rule) => state.operations[rule.class]
},

@ -30,10 +30,18 @@ import ShippedChecks from './components/Checks/index.js'
* @property {string} id - The PHP class name of the check
* @property {string} operation - Default value for the operation field
* @property {string} color - Custom color code to be applied for the operator selector
* @property {Vue} component - A vue component to handle the rendering of options
* @property {object} [options] - Deprecated: **Use `element` instead**
*
* A vue component to handle the rendering of options.
* The component should handle the v-model directive properly,
* so it needs a value property to receive data and emit an input
* event once the data has changed
* event once the data has changed.
*
* Will be removed in 03/2028.
* @property {string} [element] - A web component id as used in window.customElements.define()`.
* It is expected that the ID is prefixed with the app namespace, e.g. oca-myapp-flow_do_this_operation
* It has to emit the `update:model-value` event when a value was changed.
* The `model-value` property will be set initially with the rule operation value.
*/
/**