From bd281daa47152dc09c0f6c2bbc9e5a308d1748bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julius=20H=C3=A4rtl?= <jus@bitgrid.net>
Date: Thu, 29 Aug 2019 16:50:33 +0200
Subject: [PATCH] Move to vuex store
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Julius Härtl <jus@bitgrid.net>
---
 apps/workflowengine/src/admin.js              | 385 ------------------
 apps/workflowengine/src/components/Check.vue  | 134 +++---
 apps/workflowengine/src/components/Event.vue  | 105 +++--
 .../src/components/Operation.vue              |  39 +-
 .../components/Operations/ConvertToPdf.vue    |  59 +--
 .../src/components/Operations/Tag.vue         |  28 +-
 apps/workflowengine/src/components/Rule.vue   | 216 +++++-----
 .../src/components/Values/FileMimeType.vue    |  56 +--
 .../src/components/Values/SizeValue.vue       |  37 +-
 .../src/components/Workflow.vue               | 116 ++----
 .../src/hbs_helpers/getOperators.js           |   7 -
 .../src/hbs_helpers/selectItem.js             |   7 -
 .../src/{ => legacy}/filemimetypeplugin.js    |  56 +--
 .../src/{ => legacy}/filenameplugin.js        |  64 +--
 .../src/{ => legacy}/filesizeplugin.js        |  40 +-
 .../src/{ => legacy}/filesystemtagsplugin.js  |  50 +--
 .../requestremoteaddressplugin.js             |  64 +--
 .../src/{ => legacy}/requesttimeplugin.js     | 148 +++----
 .../src/{ => legacy}/requesturlplugin.js      |  85 ++--
 .../{ => legacy}/requestuseragentplugin.js    |  78 ++--
 .../{ => legacy}/usergroupmembershipplugin.js |  52 +--
 apps/workflowengine/src/services/Operation.js | 134 ++----
 .../src/templates/operation.handlebars        |  45 --
 .../src/templates/operations.handlebars       |   2 -
 apps/workflowengine/src/workflowengine.js     |  34 +-
 25 files changed, 746 insertions(+), 1295 deletions(-)
 delete mode 100644 apps/workflowengine/src/admin.js
 delete mode 100644 apps/workflowengine/src/hbs_helpers/getOperators.js
 delete mode 100644 apps/workflowengine/src/hbs_helpers/selectItem.js
 rename apps/workflowengine/src/{ => legacy}/filemimetypeplugin.js (53%)
 rename apps/workflowengine/src/{ => legacy}/filenameplugin.js (50%)
 rename apps/workflowengine/src/{ => legacy}/filesizeplugin.js (60%)
 rename apps/workflowengine/src/{ => legacy}/filesystemtagsplugin.js (61%)
 rename apps/workflowengine/src/{ => legacy}/requestremoteaddressplugin.js (61%)
 rename apps/workflowengine/src/{ => legacy}/requesttimeplugin.js (54%)
 rename apps/workflowengine/src/{ => legacy}/requesturlplugin.js (51%)
 rename apps/workflowengine/src/{ => legacy}/requestuseragentplugin.js (58%)
 rename apps/workflowengine/src/{ => legacy}/usergroupmembershipplugin.js (58%)
 delete mode 100644 apps/workflowengine/src/templates/operation.handlebars
 delete mode 100644 apps/workflowengine/src/templates/operations.handlebars

diff --git a/apps/workflowengine/src/admin.js b/apps/workflowengine/src/admin.js
deleted file mode 100644
index fb2af941436..00000000000
--- a/apps/workflowengine/src/admin.js
+++ /dev/null
@@ -1,385 +0,0 @@
-/**
- * @copyright Copyright (c) 2016 Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-import OperationTemplate from './templates/operation.handlebars';
-import OperationsTemplate from './templates/operations.handlebars';
-
-(function() {
-	OCA.WorkflowEngine = _.extend(OCA.WorkflowEngine || {}, {
-		availablePlugins: [],
-		availableChecks: [],
-
-		getCheckByClass: function(className) {
-			var length = OCA.WorkflowEngine.availableChecks.length;
-			for (var i = 0; i < length; i++) {
-				if (OCA.WorkflowEngine.availableChecks[i]['class'] === className) {
-					return OCA.WorkflowEngine.availableChecks[i];
-				}
-			}
-			return undefined;
-		}
-	});
-
-	/**
-	 * 888b     d888               888          888
-	 * 8888b   d8888               888          888
-	 * 88888b.d88888               888          888
-	 * 888Y88888P888  .d88b.   .d88888  .d88b.  888 .d8888b
-	 * 888 Y888P 888 d88""88b d88" 888 d8P  Y8b 888 88K
-	 * 888  Y8P  888 888  888 888  888 88888888 888 "Y8888b.
-	 * 888   "   888 Y88..88P Y88b 888 Y8b.     888      X88
-	 * 888       888  "Y88P"   "Y88888  "Y8888  888  88888P'
-	 */
-
-	/**
-	 * @class OCA.WorkflowEngine.Operation
-	 */
-	OCA.WorkflowEngine.Operation =
-		OC.Backbone.Model.extend({
-			defaults: {
-				'class': 'OCA\\WorkflowEngine\\Operation',
-				'name': '',
-				'checks': [],
-				'operation': ''
-			}
-		});
-
-	/**
-	 *  .d8888b.           888 888                   888    d8b
-	 * d88P  Y88b          888 888                   888    Y8P
-	 * 888    888          888 888                   888
-	 * 888         .d88b.  888 888  .d88b.   .d8888b 888888 888  .d88b.  88888b.  .d8888b
-	 * 888        d88""88b 888 888 d8P  Y8b d88P"    888    888 d88""88b 888 "88b 88K
-	 * 888    888 888  888 888 888 88888888 888      888    888 888  888 888  888 "Y8888b.
-	 * Y88b  d88P Y88..88P 888 888 Y8b.     Y88b.    Y88b.  888 Y88..88P 888  888      X88
-	 *  "Y8888P"   "Y88P"  888 888  "Y8888   "Y8888P  "Y888 888  "Y88P"  888  888  88888P'
-	 */
-
-	/**
-	 * @class OCA.WorkflowEngine.OperationsCollection
-	 *
-	 * collection for all configurated operations
-	 */
-	OCA.WorkflowEngine.OperationsCollection =
-		OC.Backbone.Collection.extend({
-			model: OCA.WorkflowEngine.Operation,
-			url: OC.generateUrl('apps/workflowengine/operations')
-		});
-
-	/**
-	 * 888     888 d8b
-	 * 888     888 Y8P
-	 * 888     888
-	 * Y88b   d88P 888  .d88b.  888  888  888 .d8888b
-	 *  Y88b d88P  888 d8P  Y8b 888  888  888 88K
-	 *   Y88o88P   888 88888888 888  888  888 "Y8888b.
-	 *    Y888P    888 Y8b.     Y88b 888 d88P      X88
-	 *     Y8P     888  "Y8888   "Y8888888P"   88888P'
-	 */
-
-	/**
-	 * @class OCA.WorkflowEngine.OperationView
-	 *
-	 * this creates the view for a single operation
-	 */
-	OCA.WorkflowEngine.OperationView =
-		OC.Backbone.View.extend({
-			templateId: '#operation-template',
-			events: {
-				'change .check-class': 'checkChanged',
-				'change .check-operator': 'checkChanged',
-				'change .check-value': 'checkChanged',
-				'change .operation-name': 'operationChanged',
-				'change .operation-operation': 'operationChanged',
-				'click .button-reset': 'reset',
-				'click .button-save': 'save',
-				'click .button-add': 'add',
-				'click .button-delete': 'delete',
-				'click .button-delete-check': 'deleteCheck'
-			},
-			originalModel: null,
-			hasChanged: false,
-			message: '',
-			errorMessage: '',
-			saving: false,
-			groups: [],
-			template: function(vars) {
-				return OperationTemplate(_.extend(
-					{
-						shortRuleDescTXT: t('workflowengine', 'Short rule description'),
-						addRuleTXT: t('workflowengine', 'Add rule'),
-						resetTXT: t('workflowengine', 'Reset'),
-						saveTXT: t('workflowengine', 'Save'),
-						savingTXT: t('workflowengine', 'Saving…')
-					},
-					vars
-				));
-			},
-			initialize: function() {
-				// this creates a new copy of the object to definitely have a new reference and being able to reset the model
-				this.originalModel = JSON.parse(JSON.stringify(this.model));
-				this.model.on('change', function() {
-					console.log('model changed');
-					this.hasChanged = true;
-					this.render();
-				}, this);
-
-				if (this.model.get('id') === undefined) {
-					this.hasChanged = true;
-				}
-				var self = this;
-				$.ajax({
-					url: OC.linkToOCS('cloud/groups', 2) + 'details',
-					dataType: 'json',
-					quietMillis: 100,
-				}).success(function(data) {
-					if (data.ocs.data.groups && data.ocs.data.groups.length > 0) {
-
-						data.ocs.data.groups.forEach(function(group) {
-							self.groups.push({ id: group.id, displayname: group.displayname });
-						});
-						self.render();
-
-					} else {
-						OC.Notification.error(t('workflowengine', 'Group list is empty'), { type: 'error' });
-						console.log(data);
-					}
-				}).error(function(data) {
-					OC.Notification.error(t('workflowengine', 'Unable to retrieve the group list'), { type: 'error' });
-					console.log(data);
-				});
-			},
-			delete: function() {
-				if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
-					OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.delete, this));
-					return;
-				}
-
-				this.model.destroy();
-				this.remove();
-			},
-			reset: function() {
-				this.hasChanged = false;
-				// silent is need to not trigger the change event which resets the hasChanged attribute
-				this.model.set(this.originalModel, { silent: true });
-				this.render();
-			},
-			save: function() {
-				if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
-					OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.save, this));
-					return;
-				}
-
-				var success = function(model, response, options) {
-					this.saving = false;
-					this.originalModel = JSON.parse(JSON.stringify(this.model));
-
-					this.message = t('workflowengine', 'Saved');
-					this.errorMessage = '';
-					this.render();
-				};
-				var error = function(model, response, options) {
-					this.saving = false;
-					this.hasChanged = true;
-
-					this.message = t('workflowengine', 'Saving failed:');
-					this.errorMessage = response.responseText;
-					this.render();
-				};
-				this.hasChanged = false;
-				this.saving = true;
-				this.render();
-				this.model.save(null, { success: success, error: error, context: this });
-			},
-			add: function() {
-				var checks = _.clone(this.model.get('checks')),
-					classname = OCA.WorkflowEngine.availableChecks[0]['class'],
-					operators = OCA.WorkflowEngine.availableChecks[0]['operators'];
-
-				checks.push({
-					'class': classname,
-					'operator': operators[0]['operator'],
-					'value': ''
-				});
-				this.model.set({ 'checks': checks });
-			},
-			checkChanged: function(event) {
-				var value = event.target.value,
-					id = $(event.target.parentElement).data('id'),
-					// this creates a new copy of the object to definitely have a new reference
-					checks = JSON.parse(JSON.stringify(this.model.get('checks'))),
-					key = null;
-
-				for (var i = 0; i < event.target.classList.length; i++) {
-					var className = event.target.classList[i];
-					if (className.substr(0, 'check-'.length) === 'check-') {
-						key = className.substr('check-'.length);
-						break;
-					}
-				}
-
-				if (key === null) {
-					console.warn('checkChanged triggered but element doesn\'t have any "check-" class');
-					return;
-				}
-
-				if (!_.has(checks[id], key)) {
-					console.warn('key "' + key + '" is not available in check', check);
-					return;
-				}
-
-				checks[id][key] = value;
-				// if the class is changed most likely also the operators have changed
-				// with this we set the operator to the first possible operator
-				if (key === 'class') {
-					var check = OCA.WorkflowEngine.getCheckByClass(value);
-					if (!_.isUndefined(check)) {
-						checks[id]['operator'] = check['operators'][0]['operator'];
-						checks[id]['value'] = '';
-					}
-				}
-				// model change will trigger render
-				this.model.set({ 'checks': checks });
-			},
-			deleteCheck: function(event) {
-				console.log(arguments);
-				var id = $(event.target.parentElement).data('id'),
-					checks = JSON.parse(JSON.stringify(this.model.get('checks')));
-
-				// splice removes 1 element at index `id`
-				checks.splice(id, 1);
-				// model change will trigger render
-				this.model.set({ 'checks': checks });
-			},
-			operationChanged: function(event) {
-				var value = event.target.value,
-					key = null;
-
-				for (var i = 0; i < event.target.classList.length; i++) {
-					var className = event.target.classList[i];
-					if (className.substr(0, 'operation-'.length) === 'operation-') {
-						key = className.substr('operation-'.length);
-						break;
-					}
-				}
-
-				if (key === null) {
-					console.warn('operationChanged triggered but element doesn\'t have any "operation-" class');
-					return;
-				}
-
-				if (key !== 'name' && key !== 'operation') {
-					console.warn('key "' + key + '" is no valid attribute');
-					return;
-				}
-
-				// model change will trigger render
-				this.model.set(key, value);
-			},
-			render: function() {
-				this.$el.html(this.template({
-					operation: this.model.toJSON(),
-					classes: OCA.WorkflowEngine.availableChecks,
-					hasChanged: this.hasChanged,
-					message: this.message,
-					errorMessage: this.errorMessage,
-					saving: this.saving
-				}));
-
-				var checks = this.model.get('checks');
-				_.each(this.$el.find('.check'), function(element) {
-					var $element = $(element),
-						id = $element.data('id'),
-						check = checks[id],
-						valueElement = $element.find('.check-value').first();
-					var self = this;
-
-					_.each(OCA.WorkflowEngine.availablePlugins, function(plugin) {
-						if (_.isFunction(plugin.render)) {
-							plugin.render(valueElement, check, self.groups);
-						}
-					});
-				}, this);
-
-				if (this.message !== '') {
-					// hide success messages after some time
-					_.delay(function(elements) {
-						$(elements).css('opacity', 0);
-					}, 7000, this.$el.find('.msg.success'));
-					this.message = '';
-				}
-
-				return this.$el;
-			}
-		});
-
-	/**
-	 * @class OCA.WorkflowEngine.OperationsView
-	 *
-	 * this creates the view for configured operations
-	 */
-	OCA.WorkflowEngine.OperationsView =
-		OC.Backbone.View.extend({
-			templateId: '#operations-template',
-			collection: null,
-			$el: null,
-			events: {
-				'click .button-add-operation': 'add'
-			},
-			template: function(vars) {
-				return OperationsTemplate(_.extend(
-					{
-						addRuleGroupTXT: t('workflowengine', 'Add rule group')
-					},
-					vars
-				));
-			},
-			initialize: function(classname) {
-				if (!OCA.WorkflowEngine.availablePlugins.length) {
-					OCA.WorkflowEngine.availablePlugins = OC.Plugins.getPlugins('OCA.WorkflowEngine.CheckPlugins');
-					_.each(OCA.WorkflowEngine.availablePlugins, function(plugin) {
-						if (_.isFunction(plugin.getCheck)) {
-							OCA.WorkflowEngine.availableChecks.push(plugin.getCheck(classname));
-						}
-					});
-				}
-
-				this.collection.fetch({
-					data: {
-						'class': classname
-					}
-				});
-				this.collection.once('sync', this.render, this);
-			},
-			add: function() {
-				var operation = this.collection.create();
-				this.renderOperation(operation);
-			},
-			renderOperation: function(subView) {
-				var operationsElement = this.$el.find('.operations');
-				operationsElement.append(subView.$el);
-				subView.render();
-			},
-			render: function() {
-				this.$el.html(this.template());
-				this.collection.each(this.renderOperation, this);
-			}
-		});
-})();
\ No newline at end of file
diff --git a/apps/workflowengine/src/components/Check.vue b/apps/workflowengine/src/components/Check.vue
index 86005dae268..b2e8e13c29b 100644
--- a/apps/workflowengine/src/components/Check.vue
+++ b/apps/workflowengine/src/components/Check.vue
@@ -1,86 +1,82 @@
 <template>
-	<div class="check" @click="showDelete" v-click-outside="hideDelete">
-		<Multiselect v-model="currentOption" :options="options" label="name"
-					 track-by="class" :allow-empty="false" :placeholder="t('workflowengine', 'Select a filter')"
-					 @input="updateCheck" ref="checkSelector"></Multiselect>
-		<Multiselect v-if="currentOption" v-model="currentOperator" @input="updateCheck"
-					 :options="operators" label="name" track-by="operator"
-					 :allow-empty="false" :placeholder="t('workflowengine', 'Select a comparator')"></Multiselect>
-		<component v-if="currentOperator && currentComponent" :is="currentOption.component()" v-model="check.value" />
-		<input v-else-if="currentOperator" type="text" v-model="check.value" @input="updateCheck" />
+	<div v-click-outside="hideDelete" class="check" @click="showDelete">
+		<Multiselect ref="checkSelector" v-model="currentOption" :options="options"
+			label="name" track-by="class" :allow-empty="false"
+			:placeholder="t('workflowengine', 'Select a filter')" @input="updateCheck" />
+		<Multiselect v-if="currentOption" v-model="currentOperator" :options="operators"
+			label="name" track-by="operator" :allow-empty="false"
+			:placeholder="t('workflowengine', 'Select a comparator')" @input="updateCheck" />
+		<component :is="currentOption.component()" v-if="currentOperator && currentComponent" v-model="check.value" />
+		<input v-else-if="currentOperator" v-model="check.value" type="text"
+			@input="updateCheck">
 		<Actions>
-			<ActionButton icon="icon-delete" v-if="deleteVisible || !currentOption" @click="$emit('remove')" />
+			<ActionButton v-if="deleteVisible || !currentOption" icon="icon-delete" @click="$emit('remove')" />
 		</Actions>
 	</div>
 </template>
 
 <script>
-	import { Checks } from '../services/Operation';
-	import { Multiselect, Actions, ActionButton } from 'nextcloud-vue'
-	import ClickOutside from 'vue-click-outside';
+import { Checks } from '../services/Operation'
+import { Multiselect, Actions, ActionButton } from 'nextcloud-vue'
+import ClickOutside from 'vue-click-outside'
 
-	export default {
-		name: 'Check',
-		components: {
-			ActionButton,
-			Actions,
-			Multiselect
-		},
-		directives: {
-			ClickOutside
-		},
-		props: {
-			check: {
-				type: Object,
-				required: true
-			}
-		},
-		data() {
-			return {
-				deleteVisible: false,
-				currentOption: null,
-				currentOperator: null,
-				options: [],
-			}
+export default {
+	name: 'Check',
+	components: {
+		ActionButton,
+		Actions,
+		Multiselect
+	},
+	directives: {
+		ClickOutside
+	},
+	props: {
+		check: {
+			type: Object,
+			required: true
+		}
+	},
+	data() {
+		return {
+			deleteVisible: false,
+			currentOption: null,
+			currentOperator: null,
+			options: []
+		}
+	},
+	computed: {
+		operators() {
+			if (!this.currentOption) { return [] }
+			return Checks[this.currentOption.class].operators
 		},
-		mounted() {
-			this.options = Object.values(Checks)
-			this.currentOption = Checks[this.check.class]
-			this.currentOperator = this.operators.find((operator) => operator.operator === this.check.operator)
-			this.$nextTick(() => {
-				//this.$refs.checkSelector.$el.focus()
-			})
+		currentComponent() {
+			if (!this.currentOption) { return [] }
+			const currentComponent = Checks[this.currentOption.class].component
+			return currentComponent && currentComponent()
+		}
+	},
+	mounted() {
+		this.options = Object.values(Checks)
+		this.currentOption = Checks[this.check.class]
+		this.currentOperator = this.operators.find((operator) => operator.operator === this.check.operator)
+	},
+	methods: {
+		showDelete() {
+			this.deleteVisible = true
 		},
-		computed: {
-			operators() {
-				if (!this.currentOption)
-					return []
-				return Checks[this.currentOption.class].operators
-			},
-			currentComponent() {
-				if (!this.currentOption)
-					return []
-				let currentComponent = Checks[this.currentOption.class].component
-				return currentComponent && currentComponent()
-			}
+		hideDelete() {
+			this.deleteVisible = false
 		},
-		methods: {
-			showDelete() {
-				this.deleteVisible = true
-			},
-			hideDelete() {
-				this.deleteVisible = false
-			},
-			updateCheck() {
-				if (this.check.class !== this.currentOption.class) {
-					this.currentOperator = this.operators[0]
-				}
-				this.check.class = this.currentOption.class
-				this.check.operator = this.currentOperator.operator
-				this.$emit('update', this.check)
+		updateCheck() {
+			if (this.check.class !== this.currentOption.class) {
+				this.currentOperator = this.operators[0]
 			}
+			this.check.class = this.currentOption.class
+			this.check.operator = this.currentOperator.operator
+			this.$emit('update', this.check)
 		}
 	}
+}
 </script>
 
 <style scoped lang="scss">
diff --git a/apps/workflowengine/src/components/Event.vue b/apps/workflowengine/src/components/Event.vue
index 7b39ea571fb..d05aeb0a07e 100644
--- a/apps/workflowengine/src/components/Event.vue
+++ b/apps/workflowengine/src/components/Event.vue
@@ -1,74 +1,63 @@
 <template>
 	<div>
-	<Multiselect :value="currentEvent" :options="allEvents" label="name" track-by="id" :allow-empty="false" :disabled="allEvents.length <= 1" @input="updateEvent">
-		<template slot="singleLabel" slot-scope="props">
-			<img class="option__icon" :src="props.option.icon" />
-			<span class="option__title option__title_single">{{ props.option.name }}</span>
-		</template>
-		<template slot="option" slot-scope="props">
-			<img class="option__icon" :src="props.option.icon" />
-			<span class="option__title">{{ props.option.name }}</span>
-		</template>
-	</Multiselect>
+		<div v-if="operation.isComplex && operation.fixedEntity !== ''">
+			<img class="option__icon" :src="entity.icon">
+			<span class="option__title option__title_single">{{ entity.name }}</span>
+		</div>
+		<Multiselect v-else :value="currentEvent" :options="allEvents"
+			label="eventName" track-by="id" :allow-empty="false"
+			:disabled="allEvents.length <= 1" @input="updateEvent">
+			<template slot="singleLabel" slot-scope="props">
+				<img class="option__icon" :src="props.option.entity.icon">
+				<span class="option__title option__title_single">{{ props.option.displayName }}</span>
+			</template>
+			<template slot="option" slot-scope="props">
+				<img class="option__icon" :src="props.option.entity.icon">
+				<span class="option__title">{{ props.option.displayName }}</span>
+			</template>
+		</Multiselect>
 	</div>
 </template>
 
 <script>
-	import { Multiselect } from 'nextcloud-vue'
-	import { Entities, operationService } from '../services/Operation'
+import { Multiselect } from 'nextcloud-vue'
 
-	export default {
-		name: "Event",
-		components: {
-			Multiselect
+export default {
+	name: 'Event',
+	components: {
+		Multiselect
+	},
+	props: {
+		rule: {
+			type: Object,
+			required: true
+		}
+	},
+	computed: {
+		entity() {
+			return this.$store.getters.getEntityForOperation(this.operation)
 		},
-		props: {
-			rule: {
-				type: Object,
-				required: true
-			}
+		operation() {
+			return this.$store.getters.getOperationForRule(this.rule)
 		},
-		mounted() {
-			this.updateEvent(this.currentEvent)
+		allEvents() {
+			return this.$store.getters.getEventsForOperation(this.operation)
 		},
-		computed: {
-			currentEvent() {
-				if (!this.rule.event) {
-					return this.allEvents.length > 0 ? this.allEvents[0] : null
-				}
-				return this.allEvents.find(event => event.entity === this.rule.entity && event.event === this.rule.event)
-			},
-			allEvents() {
-				return this.operation.events.map((entityEventName) => {
-					const parts = entityEventName.split('::')
-					const entityId = parts[0]
-					const eventName = parts[1]
-					const Entity = Entities.find((entity) => entity.id === entityId)
-					const Event = Entity.events.find((event) => event.eventName === eventName)
-					return {
-						entity: entityId,
-						id: entityEventName,
-						events: eventName,
-						name: Event.displayName,
-						icon: Entity.icon,
-						checks: Entity.checks,
-					}
-				})
-			},
-			operation() {
-				return operationService.get(this.rule.class)
-			}
-		},
-		methods: {
-			updateEvent(event) {
-				if (this.rule.entity !== event.entity || this.rule.events !== '["' + event.event + '"]') {
-					this.$set(this.rule, 'entity', event.entity)
-					this.$set(this.rule, 'event', event.event)
-					this.$emit('update', this.rule)
-				}
+		currentEvent() {
+			if (!this.rule.events) {
+				return this.allEvents.length > 0 ? this.allEvents[0] : null
 			}
+			return this.allEvents.find(event => event.entity.id === this.rule.entity && this.rule.events.indexOf(event.eventName) !== -1)
+		}
+	},
+	methods: {
+		updateEvent(event) {
+			this.$set(this.rule, 'entity', event.entity.id)
+			this.$set(this.rule, 'events', [event.eventName])
+			this.$store.dispatch('updateRule', this.rule)
 		}
 	}
+}
 </script>
 
 <style scoped>
diff --git a/apps/workflowengine/src/components/Operation.vue b/apps/workflowengine/src/components/Operation.vue
index 30f26eb6ec4..1ee7a2e4c9d 100644
--- a/apps/workflowengine/src/components/Operation.vue
+++ b/apps/workflowengine/src/components/Operation.vue
@@ -1,34 +1,26 @@
 <template>
-	<div class="actions__item" :class="{'colored': !!color}" :style="{ backgroundColor: color }">
-		<div class="icon" :class="icon"></div>
-		<h3>{{ title }}</h3>
-		<small>{{ description }}</small>
+	<div class="actions__item" :class="{'colored': colored}" :style="{ backgroundColor: colored ? operation.color : 'transparent' }">
+		<div class="icon" :class="operation.iconClass" :style="{ backgroundImage: operation.iconClass ? '' : `url(${operation.icon})` }" />
+		<h3>{{ operation.name }}</h3>
+		<small>{{ operation.description }}</small>
 		<slot />
 	</div>
 </template>
 
 <script>
-	export default {
-		name: "Operation",
-		props: {
-			icon: {
-				type: String,
-				required: true
-			},
-			title: {
-				type: String,
-				required: true
-			},
-			description: {
-				type: String,
-				required: true
-			},
-			color: {
-				type: String,
-				required: false
-			},
+export default {
+	name: 'Operation',
+	props: {
+		operation: {
+			type: Object,
+			required: true
+		},
+		colored: {
+			type: Boolean,
+			default: true
 		}
 	}
+}
 </script>
 
 <style scoped lang="scss">
@@ -50,6 +42,7 @@
 		background-position: center center;
 		margin-top: 10px;
 		margin-bottom: 20px;
+		background-repeat: no-repeat;
 	}
 	h3, small {
 		padding: 6px;
diff --git a/apps/workflowengine/src/components/Operations/ConvertToPdf.vue b/apps/workflowengine/src/components/Operations/ConvertToPdf.vue
index 62c53a4ee6c..5fa1676e092 100644
--- a/apps/workflowengine/src/components/Operations/ConvertToPdf.vue
+++ b/apps/workflowengine/src/components/Operations/ConvertToPdf.vue
@@ -1,38 +1,39 @@
 <template>
-	<multiselect :options="options" track-by="id" label="text" v-model="value"></multiselect>
+	<Multiselect v-model="value" :options="options" track-by="id"
+		label="text" @input="$emit('input', value.id)" />
 </template>
 
 <script>
-	const pdfConvertOptions = [
-		{
-			id: 'keep;preserve',
-			text: t('workflow_pdf_converter', 'Keep original, preserve existing PDFs'),
-		},
-		{
-			id: 'keep;overwrite',
-			text: t('workflow_pdf_converter', 'Keep original, overwrite existing PDF'),
-		},
-		{
-			id: 'delete;preserve',
-			text: t('workflow_pdf_converter', 'Delete original, preserve existing PDFs'),
-		},
-		{
-			id: 'delete;overwrite',
-			text: t('workflow_pdf_converter', 'Delete original, overwrite existing PDF'),
-		},
-	]
+import { Multiselect } from 'nextcloud-vue'
 
-	import { Multiselect } from 'nextcloud-vue'
-	export default {
-		name: "ConvertToPdf",
-		components: {Multiselect},
-		data() {
-			return {
-				options: pdfConvertOptions,
-				value: pdfConvertOptions[0]
-			}
+const pdfConvertOptions = [
+	{
+		id: 'keep;preserve',
+		text: t('workflow_pdf_converter', 'Keep original, preserve existing PDFs')
+	},
+	{
+		id: 'keep;overwrite',
+		text: t('workflow_pdf_converter', 'Keep original, overwrite existing PDF')
+	},
+	{
+		id: 'delete;preserve',
+		text: t('workflow_pdf_converter', 'Delete original, preserve existing PDFs')
+	},
+	{
+		id: 'delete;overwrite',
+		text: t('workflow_pdf_converter', 'Delete original, overwrite existing PDF')
+	}
+]
+export default {
+	name: 'ConvertToPdf',
+	components: { Multiselect },
+	data() {
+		return {
+			options: pdfConvertOptions,
+			value: pdfConvertOptions[0]
 		}
 	}
+}
 </script>
 
 <style scoped>
@@ -42,4 +43,4 @@
 		margin: auto;
 		text-align: center;
 	}
-</style>
\ No newline at end of file
+</style>
diff --git a/apps/workflowengine/src/components/Operations/Tag.vue b/apps/workflowengine/src/components/Operations/Tag.vue
index 74e4e4f977b..7a27e2b572d 100644
--- a/apps/workflowengine/src/components/Operations/Tag.vue
+++ b/apps/workflowengine/src/components/Operations/Tag.vue
@@ -1,22 +1,24 @@
 <template>
-	<multiselect :options="options" v-model="value" track-by="id" label="title" :multiple="true" :tagging="true" @input="$emit('input', value.map(item => item.id))"></multiselect>
+	<Multiselect v-model="value" :options="options" track-by="id"
+		label="title" :multiple="true" :tagging="true"
+		@input="$emit('input', value.map(item => item.id))" />
 </template>
 
 <script>
-	// TODO: fetch tags from endpoint
-	const tags = [{id: 3, title: 'foo'}, {id: 4, title: 'bar'}]
+// TODO: fetch tags from endpoint
+import { Multiselect } from 'nextcloud-vue'
 
-	import { Multiselect } from 'nextcloud-vue'
-	export default {
-		name: "Tag",
-		components: {Multiselect},
-		data() {
-			return {
-				options: tags,
-				value: null
-			}
+const tags = [{ id: 3, title: 'foo' }, { id: 4, title: 'bar' }]
+export default {
+	name: 'Tag',
+	components: { Multiselect },
+	data() {
+		return {
+			options: tags,
+			value: null
 		}
 	}
+}
 </script>
 
 <style scoped>
@@ -26,4 +28,4 @@
 		margin: auto;
 		text-align: center;
 	}
-</style>
\ No newline at end of file
+</style>
diff --git a/apps/workflowengine/src/components/Rule.vue b/apps/workflowengine/src/components/Rule.vue
index d1f5a088f51..8a446dd7ae9 100644
--- a/apps/workflowengine/src/components/Rule.vue
+++ b/apps/workflowengine/src/components/Rule.vue
@@ -4,143 +4,144 @@
 		<div class="trigger icon-confirm">
 			<p>
 				<span>{{ t('workflowengine', 'When') }}</span>
-				<Event :rule="rule" @update="updateRule"></Event>
+				<Event :rule="rule" @update="updateRule" />
 			</p>
 			<p v-for="check in rule.checks">
 				<span>{{ t('workflowengine', 'and') }}</span>
-				<Check :check="check" @update="updateRule" @remove="removeCheck(check)"></Check>
+				<Check :check="check" @update="updateRule" @remove="removeCheck(check)" />
 			</p>
 			<p>
-				<span> </span>
-				<input v-if="lastCheckComplete" type="button" class="check--add" @click="rule.checks.push({class: null, operator: null, value: null})" value="Add a new filter"/>
+				<span />
+				<input v-if="lastCheckComplete" type="button" class="check--add"
+					value="Add a new filter" @click="rule.checks.push({class: null, operator: null, value: null})">
 			</p>
 		</div>
 		<div class="action">
 			<div class="buttons">
 				<Actions>
-					<ActionButton v-if="rule.id === -1" icon="icon-close" @click="$emit('cancel')">Cancel rule creation</ActionButton>
-					<ActionButton v-else icon="icon-close" @click="deleteRule">Remove rule</ActionButton>
+					<ActionButton v-if="rule.id < -1" icon="icon-close" @click="cancelRule">
+						Cancel rule creation
+					</ActionButton>
+					<ActionButton v-else icon="icon-close" @click="deleteRule">
+						Remove rule
+					</ActionButton>
 				</Actions>
-				<button class="status-button icon" :class="ruleStatus.class" v-tooltip="ruleStatus.tooltip" @click="saveRule">{{ ruleStatus.title }}</button>
+				<button v-tooltip="ruleStatus.tooltip" class="status-button icon" :class="ruleStatus.class"
+					@click="saveRule">
+					{{ ruleStatus.title }}
+				</button>
 			</div>
-			<Operation :icon="operation.icon" :title="operation.title" :description="operation.description">
-				<component v-if="operation.options" :is="operation.options" v-model="operation.operation" @input="updateOperation" />
+			<Operation :operation="operation" :colored="false">
+				<component :is="operation.options" v-if="operation.options" v-model="rule.operation"
+					@input="updateOperation" />
 			</Operation>
 		</div>
 	</div>
 </template>
 
 <script>
-	import { Actions, ActionButton, Tooltip } from 'nextcloud-vue'
-	import Event from './Event'
-	import Check from './Check'
-	import Operation from './Operation'
-	import { operationService } from '../services/Operation'
-	import axios from 'nextcloud-axios'
-	import confirmPassword from 'nextcloud-password-confirmation'
-	import {getApiUrl} from '../helpers/api';
+import { Actions, ActionButton, Tooltip } from 'nextcloud-vue'
+import Event from './Event'
+import Check from './Check'
+import Operation from './Operation'
+
+export default {
+	name: 'Rule',
+	components: {
+		Operation, Check, Event, Actions, ActionButton
+	},
+	directives: {
+		Tooltip
+	},
+	props: {
+		rule: {
+			type: Object,
+			required: true
+		}
+	},
+	data() {
+		return {
+			editing: false,
+			checks: [],
+			error: null,
+			dirty: this.rule.id < 0,
+			checking: false
+		}
+	},
+	computed: {
+		operation() {
+			return this.$store.getters.getOperationForRule(this.rule)
+		},
+		ruleStatus() {
+			if (this.error) {
+				return {
+					title: t('workflowengine', 'The configuration is invalid'),
+					class: 'icon-close-white invalid',
+					tooltip: { placement: 'bottom', show: true, content: this.error }
+				}
+			}
+			if (!this.dirty || this.checking) {
+				return { title: 'Active', class: 'icon icon-checkmark' }
+			}
+			return { title: 'Save', class: 'icon-confirm-white primary' }
 
-	export default {
-		name: 'Rule',
-		components: {
-			Operation, Check, Event, Actions, ActionButton
 		},
-		directives: {
-			Tooltip
+		lastCheckComplete() {
+			const lastCheck = this.rule.checks[this.rule.checks.length - 1]
+			return typeof lastCheck === 'undefined' || lastCheck.class !== null
+		}
+	},
+	methods: {
+		async updateOperation(operation) {
+			this.$set(this.rule, 'operation', operation)
+			await this.updateRule()
 		},
-		props: {
-			rule: {
-				type: Object,
-				required: true,
+		async updateRule() {
+			this.checking = true
+			if (!this.dirty) {
+				this.dirty = true
+			}
+			try {
+				// TODO: add new verify endpoint
+				// let result = await axios.post(OC.generateUrl(`/apps/workflowengine/operations/test`), this.rule)
+				this.error = null
+				this.checking = false
+				this.$store.dispatch('updateRule', this.rule)
+			} catch (e) {
+				console.error('Failed to update operation', e)
+				this.error = e.response.ocs.meta.message
+				this.checking = false
 			}
 		},
-		data () {
-			return {
-				editing: false,
-				operationService,
-				checks: [],
-				error: null,
-				dirty: this.rule.id === -1,
-				checking: false
+		async saveRule() {
+			try {
+				await this.$store.dispatch('pushUpdateRule', this.rule)
+				this.dirty = false
+				this.error = null
+			} catch (e) {
+				console.error('Failed to save operation')
+				this.error = e.response.data.ocs.meta.message
 			}
 		},
-		computed: {
-			operation() {
-				return this.operationService.get(this.rule.class)
-			},
-			ruleStatus() {
-				if (this.error) {
-					return { title: 'Invalid', class: 'icon-close-white invalid', tooltip: { placement: 'bottom', show: true, content: escapeHTML(this.error) } }
-				}
-				if (!this.dirty || this.checking) {
-					return { title: 'Active', class: 'icon icon-checkmark' }
-				}
-				return { title: 'Save', class: 'icon-confirm-white primary' }
-
-
-			},
-			lastCheckComplete() {
-				const lastCheck = this.rule.checks[this.rule.checks.length-1]
-				return typeof lastCheck === 'undefined' || lastCheck.class !== null
+		async deleteRule() {
+			try {
+				await this.$store.dispatch('deleteRule', this.rule)
+			} catch (e) {
+				console.error('Failed to delete operation')
+				this.error = e.response.data.ocs.meta.message
 			}
 		},
-		methods: {
-			updateOperation(operation) {
-				this.$set(this.rule, 'operation', operation)
-			},
-			async updateRule() {
-				this.checking = true
-				if (!this.dirty) {
-					this.dirty = true
-				}
-				try {
-					// TODO: add new verify endpoint
-					//let result = await axios.post(OC.generateUrl(`/apps/workflowengine/operations/test`), this.rule)
-					this.error = null
-					this.checking = false
-				} catch (e) {
-					console.error('Failed to update operation', e)
-					this.error = e.response.ocs.meta.message
-					this.checking = false
-				}
-			},
-			async saveRule() {
-				try {
-					await confirmPassword()
-					let result
-					if (this.rule.id === -1) {
-						result = await axios.post(getApiUrl(''), {...this.rule, events: [this.rule.event]})
-						this.rule.id = result.data.ocs.data.id
-					} else {
-						result = await axios.put(getApiUrl(`/${this.rule.id}`), {...this.rule, events: [this.rule.event]})
-					}
-					this.$emit('update', this.rule)
-					this.dirty = false
-					this.error = null
-				} catch (e) {
-					console.log(e.response.data.ocs.meta.message)
-					console.error('Failed to update operation', e)
-					this.error = e.response.data.ocs.meta.message
-				}
-			},
-			async deleteRule() {
-				try {
-					await confirmPassword()
-					await axios.delete(getApiUrl(`/${this.rule.id}`))
-					this.$emit('delete')
-				} catch (e) {
-					console.error('Failed to delete operation')
-					this.error = e.response
-				}
-			},
-			removeCheck(check) {
-				const index = this.rule.checks.findIndex(item => item === check)
-				if (index !== -1) {
-					this.rule.checks.splice(index, 1)
-				}
+		cancelRule() {
+			this.$store.dispatch('removeRule', this.rule)
+		},
+		removeCheck(check) {
+			const index = this.rule.checks.findIndex(item => item === check)
+			if (index < 0) {
+				this.rule.checks.splice(index, 1)
 			}
 		}
 	}
+}
 </script>
 
 <style scoped lang="scss">
@@ -162,6 +163,7 @@
 	.status-button.invalid {
 		background-color: var(--color-warning);
 		color: #fff;
+		border: none;
 	}
 
 	.rule {
diff --git a/apps/workflowengine/src/components/Values/FileMimeType.vue b/apps/workflowengine/src/components/Values/FileMimeType.vue
index 70b8f0d984b..9913dc1e858 100644
--- a/apps/workflowengine/src/components/Values/FileMimeType.vue
+++ b/apps/workflowengine/src/components/Values/FileMimeType.vue
@@ -1,39 +1,39 @@
 <template>
-	<input type="text" />
+	<input type="text">
 </template>
 
 <script>
-	import { Multiselect } from 'nextcloud-vue'
+import { Multiselect } from 'nextcloud-vue'
 
-	export default {
-		name: 'SizeValue',
-		components: {
-			Multiselect
-		},
-		data() {
-			return {
-				predefinedTypes: [
-					{
-						icon: 'icon-picture',
-						label: 'Images',
-						pattern: '/image\\/.*/'
-					},
-					{
-						icon: 'icon-category-office',
-						label: 'Office documents',
-						pattern: '/(vnd\\.(ms-|openxmlformats-).*))$/'
-					},
-					{
-						icon: 'icon-filetype-file',
-						label: 'PDF documents',
-						pattern: 'application/pdf'
-					}
-				]
-			}
+export default {
+	name: 'SizeValue',
+	components: {
+		Multiselect
+	},
+	data() {
+		return {
+			predefinedTypes: [
+				{
+					icon: 'icon-picture',
+					label: 'Images',
+					pattern: '/image\\/.*/'
+				},
+				{
+					icon: 'icon-category-office',
+					label: 'Office documents',
+					pattern: '/(vnd\\.(ms-|openxmlformats-).*))$/'
+				},
+				{
+					icon: 'icon-filetype-file',
+					label: 'PDF documents',
+					pattern: 'application/pdf'
+				}
+			]
 		}
 	}
+}
 </script>
 
 <style scoped>
 
-</style>
\ No newline at end of file
+</style>
diff --git a/apps/workflowengine/src/components/Values/SizeValue.vue b/apps/workflowengine/src/components/Values/SizeValue.vue
index bc4378702e1..03b28f18947 100644
--- a/apps/workflowengine/src/components/Values/SizeValue.vue
+++ b/apps/workflowengine/src/components/Values/SizeValue.vue
@@ -1,28 +1,29 @@
 <template>
-	<input type="text" placeholder="1 MB" @input="$emit('input', newValue)" v-model="newValue">
+	<input v-model="newValue" type="text" placeholder="1 MB"
+		@input="$emit('input', newValue)">
 </template>
 
 <script>
-	export default {
-		name: "SizeValue",
-		props: {
-			value: {
-				type: String
-			}
-		},
-		data() {
-			return {
-				newValue: this.value
-			}
-		},
-		watch: {
-			value() {
-				this.newValue = this.value
-			}
+export default {
+	name: 'SizeValue',
+	props: {
+		value: {
+			type: String
+		}
+	},
+	data() {
+		return {
+			newValue: this.value
+		}
+	},
+	watch: {
+		value() {
+			this.newValue = this.value
 		}
 	}
+}
 </script>
 
 <style scoped>
 
-</style>
\ No newline at end of file
+</style>
diff --git a/apps/workflowengine/src/components/Workflow.vue b/apps/workflowengine/src/components/Workflow.vue
index 0525722666e..986b6f5197c 100644
--- a/apps/workflowengine/src/components/Workflow.vue
+++ b/apps/workflowengine/src/components/Workflow.vue
@@ -4,93 +4,68 @@
 			<h2>{{ t('workflowengine', 'Workflows') }}</h2>
 
 			<transition-group name="slide" tag="div" class="actions">
-				<Operation v-for="operation in getMainOperations" :key="operation.class"
-						   :icon="operation.icon" :title="operation.title" :description="operation.description" :color="operation.color"
-						   @click.native="createNewRule(operation)"></Operation>
+				<Operation v-for="operation in getMainOperations" :key="operation.id" :operation="operation"
+					@click.native="createNewRule(operation)" />
 			</transition-group>
 
-			<div class="actions__more" v-if="hasMoreOperations">
+			<div v-if="hasMoreOperations" class="actions__more">
 				<button class="icon" :class="showMoreOperations ? 'icon-triangle-n' : 'icon-triangle-s'"
-						@click="showMoreOperations=!showMoreOperations">
+					@click="showMoreOperations=!showMoreOperations">
 					{{ showMoreOperations ? t('workflowengine', 'Show less') : t('workflowengine', 'Show more') }}
 				</button>
 			</div>
 		</div>
 
-		<transition-group name="slide" v-if="rules.length > 0">
-			<Rule v-for="rule in rules" :key="rule.id" :rule="rule" @delete="removeRule(rule)" @cancel="removeRule(rule)" @update="updateRule"></Rule>
+		<transition-group v-if="rules.length > 0" name="slide">
+			<Rule v-for="rule in rules" :key="rule.id" :rule="rule" />
 		</transition-group>
-
 	</div>
 </template>
 
 <script>
-	import Rule from './Rule'
-	import Operation from './Operation'
-	import { operationService } from '../services/Operation'
-	import axios from 'nextcloud-axios'
-	import { getApiUrl } from '../helpers/api';
-
-	const ACTION_LIMIT = 3
-
-	export default {
-		name: 'Workflow',
-		components: {
-			Operation,
-			Rule
-		},
-		async mounted() {
-			const { data } = await axios.get(getApiUrl(''))
-			this.rules = Object.values(data.ocs.data).flat()
-		},
-		data() {
-			return {
-				scope: OCP.InitialState.loadState('workflowengine', 'scope'),
-				operations: operationService,
-				showMoreOperations: false,
-				rules: []
-			}
-		},
-		computed: {
-			hasMoreOperations() {
-				return Object.keys(this.operations.getAll()).length > ACTION_LIMIT
-			},
-			getMainOperations() {
-				if (this.showMoreOperations) {
-					return Object.values(this.operations.getAll())
-				}
-				return Object.values(this.operations.getAll()).slice(0, ACTION_LIMIT)
-			},
-			getMoreOperations() {
-				return Object.values(this.operations.getAll()).slice(ACTION_LIMIT)
-
-			}
+import Rule from './Rule'
+import Operation from './Operation'
+import { mapGetters, mapState } from 'vuex'
+
+const ACTION_LIMIT = 3
+
+export default {
+	name: 'Workflow',
+	components: {
+		Operation,
+		Rule
+	},
+	data() {
+		return {
+			showMoreOperations: false
+		}
+	},
+	computed: {
+		...mapGetters({
+			rules: 'getRules'
+		}),
+		...mapState({
+			operations: 'operations'
+		}),
+		hasMoreOperations() {
+			return Object.keys(this.operations).length > ACTION_LIMIT
 		},
-		methods: {
-			updateRule(rule) {
-				let index = this.rules.findIndex((item) => rule === item)
-				this.$set(this.rules, index, rule)
-			},
-			removeRule(rule) {
-				let index = this.rules.findIndex((item) => rule === item)
-				this.rules.splice(index, 1)
-			},
-			showAllOperations() {
-
-			},
-			createNewRule(operation) {
-				this.rules.unshift({
-					id: -1,
-					class: operation.class,
-					entity: undefined,
-					event: undefined,
-					name: '', // unused in the new ui, there for legacy reasons
-					checks: [],
-					operation: operation.operation || ''
-				})
+		getMainOperations() {
+			if (this.showMoreOperations) {
+				return Object.values(this.operations)
 			}
+			return Object.values(this.operations).slice(0, ACTION_LIMIT)
+		}
+	},
+	mounted() {
+		this.$store.dispatch('fetchRules')
+	},
+	methods: {
+		createNewRule(operation) {
+			this.$store.dispatch('createNewRule', operation)
 		}
 	}
+}
 </script>
 
 <style scoped lang="scss">
@@ -119,7 +94,6 @@
 		background-position: 10px center;
 	}
 
-
 	.slide-enter-active {
 		-moz-transition-duration: 0.3s;
 		-webkit-transition-duration: 0.3s;
diff --git a/apps/workflowengine/src/hbs_helpers/getOperators.js b/apps/workflowengine/src/hbs_helpers/getOperators.js
deleted file mode 100644
index 4e3606fe82c..00000000000
--- a/apps/workflowengine/src/hbs_helpers/getOperators.js
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = function(classname) {
-	var check = OCA.WorkflowEngine.getCheckByClass(classname);
-	if (!_.isUndefined(check)) {
-		return check['operators'];
-	}
-	return [];
-}
diff --git a/apps/workflowengine/src/hbs_helpers/selectItem.js b/apps/workflowengine/src/hbs_helpers/selectItem.js
deleted file mode 100644
index 594e3debadd..00000000000
--- a/apps/workflowengine/src/hbs_helpers/selectItem.js
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = function(currentValue, itemValue) {
-	if (currentValue === itemValue) {
-		return 'selected="selected"';
-	}
-
-	return "";
-}
diff --git a/apps/workflowengine/src/filemimetypeplugin.js b/apps/workflowengine/src/legacy/filemimetypeplugin.js
similarity index 53%
rename from apps/workflowengine/src/filemimetypeplugin.js
rename to apps/workflowengine/src/legacy/filemimetypeplugin.js
index 6b929b2aad5..2b29c4fcbb8 100644
--- a/apps/workflowengine/src/filemimetypeplugin.js
+++ b/apps/workflowengine/src/legacy/filemimetypeplugin.js
@@ -17,61 +17,61 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import FileMimeType from './components/Values/FileMimeType'
+import FileMimeType from './../components/Values/FileMimeType'
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.FileMimeTypePlugin = {
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\FileMimeType',
-				'name': t('workflowengine', 'File MIME type'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not')},
-					{'operator': 'matches', 'name': t('workflowengine', 'matches')},
-					{'operator': '!matches', 'name': t('workflowengine', 'does not match')}
+				class: 'OCA\\WorkflowEngine\\Check\\FileMimeType',
+				name: t('workflowengine', 'File MIME type'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is') },
+					{ operator: '!is', name: t('workflowengine', 'is not') },
+					{ operator: 'matches', name: t('workflowengine', 'matches') },
+					{ operator: '!matches', name: t('workflowengine', 'does not match') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\FileMimeType') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\FileMimeType') {
+				return
 			}
 
-			var placeholder = 'text/plain';
-			if (check['operator'] === 'matches' || check['operator'] === '!matches') {
-				placeholder = '/^text\\/(plain|html)$/i';
+			var placeholder = 'text/plain'
+			if (check.operator === 'matches' || check.operator === '!matches') {
+				placeholder = '/^text\\/(plain|html)$/i'
 
-				if (this._validateRegex(check['value'])) {
-					$(element).removeClass('invalid-input');
+				if (this._validateRegex(check.value)) {
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			}
 
 			$(element).css('width', '250px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 		},
 
 		_validateRegex: function(string) {
-			var regexRegex = /^\/(.*)\/([gui]{0,3})$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+			var regexRegex = /^\/(.*)\/([gui]{0,3})$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		},
 
-		component: function () {
+		component: function() {
 			return FileMimeType
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileMimeTypePlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileMimeTypePlugin)
diff --git a/apps/workflowengine/src/filenameplugin.js b/apps/workflowengine/src/legacy/filenameplugin.js
similarity index 50%
rename from apps/workflowengine/src/filenameplugin.js
rename to apps/workflowengine/src/legacy/filenameplugin.js
index 7d8018c29cd..637e08ccbea 100644
--- a/apps/workflowengine/src/filenameplugin.js
+++ b/apps/workflowengine/src/legacy/filenameplugin.js
@@ -18,61 +18,61 @@
  *
  */
 
-(function () {
+(function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.FileNamePlugin = {
-		getCheck: function () {
+		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\FileName',
-				'name': t('workflowengine', 'File name'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not')},
+				class: 'OCA\\WorkflowEngine\\Check\\FileName',
+				name: t('workflowengine', 'File name'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is') },
+					{ operator: '!is', name: t('workflowengine', 'is not') },
 					{
-						'operator': 'matches',
-						'name': t('workflowengine', 'matches')
+						operator: 'matches',
+						name: t('workflowengine', 'matches')
 					},
 					{
-						'operator': '!matches',
-						'name': t('workflowengine', 'does not match')
+						operator: '!matches',
+						name: t('workflowengine', 'does not match')
 					}
 				]
-			};
+			}
 		},
-		render: function (element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\FileName') {
-				return;
+		render: function(element, check) {
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\FileName') {
+				return
 			}
 
-			var placeholder = 'dummy.jpg';
-			if (check['operator'] === 'matches' || check['operator'] === '!matches') {
-				placeholder = '/^dummy-.+$/i';
+			var placeholder = 'dummy.jpg'
+			if (check.operator === 'matches' || check.operator === '!matches') {
+				placeholder = '/^dummy-.+$/i'
 
-				if (this._validateRegex(check['value'])) {
-					$(element).removeClass('invalid-input');
+				if (this._validateRegex(check.value)) {
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			}
 
 			$(element).css('width', '250px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 		},
 
-		_validateRegex: function (string) {
-			var regexRegex = /^\/(.*)\/([gui]{0,3})$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+		_validateRegex: function(string) {
+			var regexRegex = /^\/(.*)\/([gui]{0,3})$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileNamePlugin);
\ No newline at end of file
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileNamePlugin)
diff --git a/apps/workflowengine/src/filesizeplugin.js b/apps/workflowengine/src/legacy/filesizeplugin.js
similarity index 60%
rename from apps/workflowengine/src/filesizeplugin.js
rename to apps/workflowengine/src/legacy/filesizeplugin.js
index ebd72dcd2f4..fcb81bd3397 100644
--- a/apps/workflowengine/src/filesizeplugin.js
+++ b/apps/workflowengine/src/legacy/filesizeplugin.js
@@ -17,43 +17,43 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-import SizeValue from './components/Values/SizeValue'
+import SizeValue from './../components/Values/SizeValue'
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.FileSizePlugin = {
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\FileSize',
-				'name': t('workflowengine', 'File size (upload)'),
-				'operators': [
-					{'operator': 'less', 'name': t('workflowengine', 'less')},
-					{'operator': '!greater', 'name': t('workflowengine', 'less or equals')},
-					{'operator': '!less', 'name': t('workflowengine', 'greater or equals')},
-					{'operator': 'greater', 'name': t('workflowengine', 'greater')}
+				class: 'OCA\\WorkflowEngine\\Check\\FileSize',
+				name: t('workflowengine', 'File size (upload)'),
+				operators: [
+					{ operator: 'less', name: t('workflowengine', 'less') },
+					{ operator: '!greater', name: t('workflowengine', 'less or equals') },
+					{ operator: '!less', name: t('workflowengine', 'greater or equals') },
+					{ operator: 'greater', name: t('workflowengine', 'greater') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\FileSize') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\FileSize') {
+				return
 			}
 
-			var placeholder = '12 MB'; // Do not translate!!!
+			var placeholder = '12 MB' // Do not translate!!!
 			$(element).css('width', '250px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 		},
-		component: function () {
+		component: function() {
 			return SizeValue
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileSizePlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileSizePlugin)
diff --git a/apps/workflowengine/src/filesystemtagsplugin.js b/apps/workflowengine/src/legacy/filesystemtagsplugin.js
similarity index 61%
rename from apps/workflowengine/src/filesystemtagsplugin.js
rename to apps/workflowengine/src/legacy/filesystemtagsplugin.js
index e66a35b73b9..e945c79195c 100644
--- a/apps/workflowengine/src/filesystemtagsplugin.js
+++ b/apps/workflowengine/src/legacy/filesystemtagsplugin.js
@@ -20,28 +20,28 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.FileSystemTagsPlugin = {
 		getCheck: function() {
-			this.collection = OC.SystemTags.collection;
+			this.collection = OC.SystemTags.collection
 
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\FileSystemTags',
-				'name': t('workflowengine', 'File system tag'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is tagged with')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not tagged with')}
+				class: 'OCA\\WorkflowEngine\\Check\\FileSystemTags',
+				name: t('workflowengine', 'File system tag'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is tagged with') },
+					{ operator: '!is', name: t('workflowengine', 'is not tagged with') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\FileSystemTags') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\FileSystemTags') {
+				return
 			}
 
-			$(element).css('width', '400px');
+			$(element).css('width', '400px')
 
 			$(element).select2({
 				allowClear: false,
@@ -50,29 +50,29 @@
 				query: _.debounce(function(query) {
 					query.callback({
 						results: OC.SystemTags.collection.filterByName(query.term)
-					});
+					})
 				}, 100, true),
 				id: function(element) {
-					return element.get('id');
+					return element.get('id')
 				},
 				initSelection: function(element, callback) {
-					callback($(element).val());
+					callback($(element).val())
 				},
-				formatResult: function (tag) {
-					return OC.SystemTags.getDescriptiveTag(tag);
+				formatResult: function(tag) {
+					return OC.SystemTags.getDescriptiveTag(tag)
 				},
-				formatSelection: function (tagId) {
-					var tag = OC.SystemTags.collection.get(tagId);
+				formatSelection: function(tagId) {
+					var tag = OC.SystemTags.collection.get(tagId)
 					if (!_.isUndefined(tag)) {
-						return OC.SystemTags.getDescriptiveTag(tag);
+						return OC.SystemTags.getDescriptiveTag(tag)
 					}
 				},
 				escapeMarkup: function(m) {
-					return m;
+					return m
 				}
-			});
+			})
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileSystemTagsPlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileSystemTagsPlugin)
diff --git a/apps/workflowengine/src/requestremoteaddressplugin.js b/apps/workflowengine/src/legacy/requestremoteaddressplugin.js
similarity index 61%
rename from apps/workflowengine/src/requestremoteaddressplugin.js
rename to apps/workflowengine/src/legacy/requestremoteaddressplugin.js
index a66d6f51f0f..b6f7d02dd46 100644
--- a/apps/workflowengine/src/requestremoteaddressplugin.js
+++ b/apps/workflowengine/src/legacy/requestremoteaddressplugin.js
@@ -20,64 +20,64 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.RequestRemoteAddressPlugin = {
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress',
-				'name': t('workflowengine', 'Request remote address'),
-				'operators': [
-					{'operator': 'matchesIPv4', 'name': t('workflowengine', 'matches IPv4')},
-					{'operator': '!matchesIPv4', 'name': t('workflowengine', 'does not match IPv4')},
-					{'operator': 'matchesIPv6', 'name': t('workflowengine', 'matches IPv6')},
-					{'operator': '!matchesIPv6', 'name': t('workflowengine', 'does not match IPv6')}
+				class: 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress',
+				name: t('workflowengine', 'Request remote address'),
+				operators: [
+					{ operator: 'matchesIPv4', name: t('workflowengine', 'matches IPv4') },
+					{ operator: '!matchesIPv4', name: t('workflowengine', 'does not match IPv4') },
+					{ operator: 'matchesIPv6', name: t('workflowengine', 'matches IPv6') },
+					{ operator: '!matchesIPv6', name: t('workflowengine', 'does not match IPv6') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress') {
+				return
 			}
 
-			var placeholder = '127.0.0.1/32'; // Do not translate!!!
-			if (check['operator'] === 'matchesIPv6' || check['operator'] === '!matchesIPv6') {
-				placeholder = '::1/128'; // Do not translate!!!
-				if (this._validateIPv6(check['value'])) {
-					$(element).removeClass('invalid-input');
+			var placeholder = '127.0.0.1/32' // Do not translate!!!
+			if (check.operator === 'matchesIPv6' || check.operator === '!matchesIPv6') {
+				placeholder = '::1/128' // Do not translate!!!
+				if (this._validateIPv6(check.value)) {
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			} else {
-				if (this._validateIPv4(check['value'])) {
-					$(element).removeClass('invalid-input');
+				if (this._validateIPv4(check.value)) {
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			}
 
 			$(element).css('width', '300px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 		},
 
 		_validateIPv4: function(string) {
-			var regexRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[1-2][0-9]|[1-9])$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+			var regexRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[1-2][0-9]|[1-9])$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		},
 
 		_validateIPv6: function(string) {
-			var regexRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(1([01][0-9]|2[0-8])|[1-9][0-9]|[0-9])$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+			var regexRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(1([01][0-9]|2[0-8])|[1-9][0-9]|[0-9])$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestRemoteAddressPlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestRemoteAddressPlugin)
diff --git a/apps/workflowengine/src/requesttimeplugin.js b/apps/workflowengine/src/legacy/requesttimeplugin.js
similarity index 54%
rename from apps/workflowengine/src/requesttimeplugin.js
rename to apps/workflowengine/src/legacy/requesttimeplugin.js
index 111b2bb7437..eaeae287da4 100644
--- a/apps/workflowengine/src/requesttimeplugin.js
+++ b/apps/workflowengine/src/legacy/requesttimeplugin.js
@@ -20,81 +20,81 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.RequestTimePlugin = {
 		timezones: [
-			"Europe/Berlin",
-			"Europe/London"
+			'Europe/Berlin',
+			'Europe/London'
 		],
 		_$element: null,
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\RequestTime',
-				'name': t('workflowengine', 'Request time'),
-				'operators': [
-					{'operator': 'in', 'name': t('workflowengine', 'between')},
-					{'operator': '!in', 'name': t('workflowengine', 'not between')}
+				class: 'OCA\\WorkflowEngine\\Check\\RequestTime',
+				name: t('workflowengine', 'Request time'),
+				operators: [
+					{ operator: 'in', name: t('workflowengine', 'between') },
+					{ operator: '!in', name: t('workflowengine', 'not between') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\RequestTime') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestTime') {
+				return
 			}
 
-			var startTime = '09:00',
-				endTime = '18:00',
-				timezone = jstz.determine().name(),
-				$element = $(element);
+			var startTime = '09:00'
+			var endTime = '18:00'
+			var timezone = jstz.determine().name()
+			var $element = $(element)
 
-			if (_.isString(check['value']) && check['value'] !== '') {
-				var value = JSON.parse(check['value']),
-					splittedStart = value[0].split(' ', 2),
-					splittedEnd = value[1].split(' ', 2);
+			if (_.isString(check.value) && check.value !== '') {
+				var value = JSON.parse(check.value)
+				var splittedStart = value[0].split(' ', 2)
+				var splittedEnd = value[1].split(' ', 2)
 
-				startTime = splittedStart[0];
-				endTime = splittedEnd[0];
-				timezone = splittedStart[1];
+				startTime = splittedStart[0]
+				endTime = splittedEnd[0]
+				timezone = splittedStart[1]
 			}
 
-			var valueJSON = JSON.stringify([startTime + ' ' + timezone, endTime + ' ' + timezone]);
-			if (check['value'] !== valueJSON) {
-				check['value'] = valueJSON;
-				$element.val(valueJSON);
+			var valueJSON = JSON.stringify([startTime + ' ' + timezone, endTime + ' ' + timezone])
+			if (check.value !== valueJSON) {
+				check.value = valueJSON
+				$element.val(valueJSON)
 			}
 
-			$element.css('display', 'none');
+			$element.css('display', 'none')
 
 			$('<input>')
 				.attr('type', 'text')
 				.attr('placeholder', t('workflowengine', 'Start'))
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: '16:00'}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: '16:00' }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
 				})
 				.addClass('start')
 				.val(startTime)
-				.insertBefore($element);
+				.insertBefore($element)
 			$('<input>')
 				.attr('type', 'text')
 				.attr('placeholder', t('workflowengine', 'End'))
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: '16:00'}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: '16:00' }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
 				})
 				.addClass('end')
 				.val(endTime)
-				.insertBefore($element);
+				.insertBefore($element)
 
 			var timezoneInput = $('<input>')
 				.attr('type', 'hidden')
 				.css('width', '250px')
 				.insertBefore($element)
-				.val(timezone);
+				.val(timezone)
 
 			timezoneInput.select2({
 				allowClear: false,
@@ -104,93 +104,93 @@
 					url: OC.generateUrl('apps/workflowengine/timezones'),
 					dataType: 'json',
 					quietMillis: 100,
-					data: function (term) {
+					data: function(term) {
 						if (term === '') {
 							// Default search in the same continent...
-							term = jstz.determine().name().split('/');
-							term = term[0];
+							term = jstz.determine().name().split('/')
+							term = term[0]
 						}
 						return {
 							search: term
-						};
+						}
 					},
-					results: function (response) {
-						var results = [];
+					results: function(response) {
+						var results = []
 						$.each(response, function(timezone) {
-							results.push({ id: timezone });
-						});
+							results.push({ id: timezone })
+						})
 
 						return {
 							results: results,
 							more: false
-						};
+						}
 					}
 				},
-				initSelection: function (element, callback) {
-					callback(element.val());
+				initSelection: function(element, callback) {
+					callback(element.val())
 				},
-				formatResult: function (element) {
-					return '<span>' + element.id + '</span>';
+				formatResult: function(element) {
+					return '<span>' + element.id + '</span>'
 				},
-				formatSelection: function (element) {
+				formatSelection: function(element) {
 					if (!_.isUndefined(element.id)) {
-						element = element.id;
+						element = element.id
 					}
-					return '<span>' + element + '</span>';
+					return '<span>' + element + '</span>'
 				}
-			});
+			})
 
 			// Has to be added after select2 for `event.target.classList`
-			timezoneInput.addClass('timezone');
+			timezoneInput.addClass('timezone')
 
 			$element.parent()
 				.on('change', '.start', _.bind(this.update, this))
 				.on('change', '.end', _.bind(this.update, this))
-				.on('change', '.timezone', _.bind(this.update, this));
+				.on('change', '.timezone', _.bind(this.update, this))
 
-			this._$element = $element;
+			this._$element = $element
 		},
 		update: function(event) {
-			var value = event.target.value,
-				key = null;
+			var value = event.target.value
+			var key = null
 
 			for (var i = 0; i < event.target.classList.length; i++) {
-				key = event.target.classList[i];
+				key = event.target.classList[i]
 			}
 
 			if (key === null) {
-				console.warn('update triggered but element doesn\'t have any class');
-				return;
+				console.warn('update triggered but element doesn\'t have any class')
+				return
 			}
 
-			var data = JSON.parse(this._$element.val()),
-				startTime = moment(data[0].split(' ', 2)[0], 'H:m Z'),
-				endTime = moment(data[1].split(' ', 2)[0], 'H:m Z'),
-				timezone = data[0].split(' ', 2)[1];
+			var data = JSON.parse(this._$element.val())
+			var startTime = moment(data[0].split(' ', 2)[0], 'H:m Z')
+			var endTime = moment(data[1].split(' ', 2)[0], 'H:m Z')
+			var timezone = data[0].split(' ', 2)[1]
 
 			if (key === 'start' || key === 'end') {
-				var parsedDate = moment(value, ['H:m', 'h:m a'], true).format('HH:mm');
+				var parsedDate = moment(value, ['H:m', 'h:m a'], true).format('HH:mm')
 
 				if (parsedDate === 'Invalid date') {
-					return;
+					return
 				}
 
-				var indexValue = 0;
+				var indexValue = 0
 				if (key === 'end') {
-					indexValue = 1;
+					indexValue = 1
 				}
-				data[indexValue] = parsedDate + ' ' + timezone;
+				data[indexValue] = parsedDate + ' ' + timezone
 			}
 
 			if (key === 'timezone') {
-				data[0] = startTime.format('HH:mm') + ' ' + value;
-				data[1] = endTime.format('HH:mm') + ' ' + value;
+				data[0] = startTime.format('HH:mm') + ' ' + value
+				data[1] = endTime.format('HH:mm') + ' ' + value
 			}
 
-			this._$element.val(JSON.stringify(data));
-			this._$element.trigger('change');
+			this._$element.val(JSON.stringify(data))
+			this._$element.trigger('change')
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestTimePlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestTimePlugin)
diff --git a/apps/workflowengine/src/requesturlplugin.js b/apps/workflowengine/src/legacy/requesturlplugin.js
similarity index 51%
rename from apps/workflowengine/src/requesturlplugin.js
rename to apps/workflowengine/src/legacy/requesturlplugin.js
index 7c81deaaf33..7e13422387f 100644
--- a/apps/workflowengine/src/requesturlplugin.js
+++ b/apps/workflowengine/src/legacy/requesturlplugin.js
@@ -20,98 +20,97 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.RequestURLPlugin = {
 		predefinedValues: ['webdav'],
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\RequestURL',
-				'name': t('workflowengine', 'Request URL'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not')},
-					{'operator': 'matches', 'name': t('workflowengine', 'matches')},
-					{'operator': '!matches', 'name': t('workflowengine', 'does not match')}
+				class: 'OCA\\WorkflowEngine\\Check\\RequestURL',
+				name: t('workflowengine', 'Request URL'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is') },
+					{ operator: '!is', name: t('workflowengine', 'is not') },
+					{ operator: 'matches', name: t('workflowengine', 'matches') },
+					{ operator: '!matches', name: t('workflowengine', 'does not match') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\RequestURL') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestURL') {
+				return
 			}
 
-			var placeholder = 'https://localhost/index.php';
+			var placeholder = 'https://localhost/index.php'
 
-			if (check['operator'] === 'matches' || check['operator'] === '!matches') {
-				placeholder = '/^https\\:\\/\\/localhost\\/index\\.php$/i';
+			if (check.operator === 'matches' || check.operator === '!matches') {
+				placeholder = '/^https\\:\\/\\/localhost\\/index\\.php$/i'
 			}
 
 			$(element).css('width', '250px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 
-			if (check['operator'] === 'matches' || check['operator'] === '!matches') {
-				if (this._validateRegex(check['value'])) {
-					$(element).removeClass('invalid-input');
+			if (check.operator === 'matches' || check.operator === '!matches') {
+				if (this._validateRegex(check.value)) {
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			} else {
-				var self = this,
-					data = [
+				var self = this
+				var data = [
 					{
 						text: t('workflowengine', 'Predefined URLs'),
 						children: [
-							{id: 'webdav', text: t('workflowengine', 'Files WebDAV')}
+							{ id: 'webdav', text: t('workflowengine', 'Files WebDAV') }
 						]
 					}
-				];
-				if (this.predefinedValues.indexOf(check['value']) === -1) {
+				]
+				if (this.predefinedValues.indexOf(check.value) === -1) {
 					data.unshift({
-						id: check['value'],
-						text: check['value']
+						id: check.value,
+						text: check.value
 					})
 				}
 
-
 				$(element).select2({
 					data: data,
 					createSearchChoice: function(term) {
-						if (self.predefinedValues.indexOf(check['value']) === -1) {
+						if (self.predefinedValues.indexOf(check.value) === -1) {
 							return {
 								id: term,
 								text: term
-							};
+							}
 						}
 					},
 					id: function(element) {
-						return element.id;
+						return element.id
 					},
-					formatResult: function (tag) {
-						return tag.text;
+					formatResult: function(tag) {
+						return tag.text
 					},
-					formatSelection: function (tag) {
-						return tag.text;
+					formatSelection: function(tag) {
+						return tag.text
 					},
 					escapeMarkup: function(m) {
-						return m;
+						return m
 					}
 				})
 			}
 		},
 
 		_validateRegex: function(string) {
-			var regexRegex = /^\/(.*)\/([gui]{0,3})$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+			var regexRegex = /^\/(.*)\/([gui]{0,3})$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestURLPlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestURLPlugin)
diff --git a/apps/workflowengine/src/requestuseragentplugin.js b/apps/workflowengine/src/legacy/requestuseragentplugin.js
similarity index 58%
rename from apps/workflowengine/src/requestuseragentplugin.js
rename to apps/workflowengine/src/legacy/requestuseragentplugin.js
index 881ea4b8ac7..5480e4ccc8b 100644
--- a/apps/workflowengine/src/requestuseragentplugin.js
+++ b/apps/workflowengine/src/legacy/requestuseragentplugin.js
@@ -20,66 +20,66 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.RequestUserAgentPlugin = {
 		predefinedValues: ['android', 'ios', 'desktop'],
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\RequestUserAgent',
-				'name': t('workflowengine', 'Request user agent'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not')},
-					{'operator': 'matches', 'name': t('workflowengine', 'matches')},
-					{'operator': '!matches', 'name': t('workflowengine', 'does not match')}
+				class: 'OCA\\WorkflowEngine\\Check\\RequestUserAgent',
+				name: t('workflowengine', 'Request user agent'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is') },
+					{ operator: '!is', name: t('workflowengine', 'is not') },
+					{ operator: 'matches', name: t('workflowengine', 'matches') },
+					{ operator: '!matches', name: t('workflowengine', 'does not match') }
 				]
-			};
+			}
 		},
 		render: function(element, check) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\RequestUserAgent') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestUserAgent') {
+				return
 			}
 
-			var placeholder = 'Mozilla/5.0 User Agent';
+			var placeholder = 'Mozilla/5.0 User Agent'
 
 			if (check.operator === 'matches' || check.operator === '!matches') {
-				placeholder = '/^Mozilla\\/5\\.0 (.*)$/i';
+				placeholder = '/^Mozilla\\/5\\.0 (.*)$/i'
 			}
 
 			$(element).css('width', '250px')
 				.attr('placeholder', placeholder)
-				.attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: placeholder}))
+				.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: placeholder }))
 				.addClass('has-tooltip')
 				.tooltip({
 					placement: 'bottom'
-				});
+				})
 
 			if (check.operator === 'matches' || check.operator === '!matches') {
 				if (this._validateRegex(check.value)) {
-					$(element).removeClass('invalid-input');
+					$(element).removeClass('invalid-input')
 				} else {
-					$(element).addClass('invalid-input');
+					$(element).addClass('invalid-input')
 				}
 			} else {
-				var self = this,
-					data = [
+				var self = this
+				var data = [
 					{
 						text: t('workflowengine', 'Sync clients'),
 						children: [
-							{id: 'android', text: t('workflowengine', 'Android client')},
-							{id: 'ios', text: t('workflowengine', 'iOS client')},
-							{id: 'desktop', text: t('workflowengine', 'Desktop client')},
-							{id: 'mail', text: t('workflowengine', 'Thunderbird & Outlook addons')}
+							{ id: 'android', text: t('workflowengine', 'Android client') },
+							{ id: 'ios', text: t('workflowengine', 'iOS client') },
+							{ id: 'desktop', text: t('workflowengine', 'Desktop client') },
+							{ id: 'mail', text: t('workflowengine', 'Thunderbird & Outlook addons') }
 						]
 					}
-				];
+				]
 				if (this.predefinedValues.indexOf(check.value) === -1) {
 					data.unshift({
 						id: check.value,
 						text: check.value
-					});
+					})
 				}
 
 				$(element).select2({
@@ -89,31 +89,31 @@
 							return {
 								id: term,
 								text: term
-							};
+							}
 						}
 					},
 					id: function(element) {
-						return element.id;
+						return element.id
 					},
-					formatResult: function (tag) {
-						return tag.text;
+					formatResult: function(tag) {
+						return tag.text
 					},
-					formatSelection: function (tag) {
-						return tag.text;
+					formatSelection: function(tag) {
+						return tag.text
 					},
 					escapeMarkup: function(m) {
-						return m;
+						return m
 					}
 				})
 			}
 		},
 
 		_validateRegex: function(string) {
-			var regexRegex = /^\/(.*)\/([gui]{0,3})$/,
-				result = regexRegex.exec(string);
-			return result !== null;
+			var regexRegex = /^\/(.*)\/([gui]{0,3})$/
+			var result = regexRegex.exec(string)
+			return result !== null
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestUserAgentPlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestUserAgentPlugin)
diff --git a/apps/workflowengine/src/usergroupmembershipplugin.js b/apps/workflowengine/src/legacy/usergroupmembershipplugin.js
similarity index 58%
rename from apps/workflowengine/src/usergroupmembershipplugin.js
rename to apps/workflowengine/src/legacy/usergroupmembershipplugin.js
index 53f35fedf2d..6d60e9e4d66 100644
--- a/apps/workflowengine/src/usergroupmembershipplugin.js
+++ b/apps/workflowengine/src/legacy/usergroupmembershipplugin.js
@@ -20,56 +20,56 @@
 
 (function() {
 
-	OCA.WorkflowEngine = OCA.WorkflowEngine || {};
-	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {};
+	OCA.WorkflowEngine = OCA.WorkflowEngine || {}
+	OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {}
 
 	OCA.WorkflowEngine.Plugins.UserGroupMembershipPlugin = {
 		getCheck: function() {
 			return {
-				'class': 'OCA\\WorkflowEngine\\Check\\UserGroupMembership',
-				'name': t('workflowengine', 'User group membership'),
-				'operators': [
-					{'operator': 'is', 'name': t('workflowengine', 'is member of')},
-					{'operator': '!is', 'name': t('workflowengine', 'is not member of')}
+				class: 'OCA\\WorkflowEngine\\Check\\UserGroupMembership',
+				name: t('workflowengine', 'User group membership'),
+				operators: [
+					{ operator: 'is', name: t('workflowengine', 'is member of') },
+					{ operator: '!is', name: t('workflowengine', 'is not member of') }
 				]
-			};
+			}
 		},
 		render: function(element, check, groups) {
-			if (check['class'] !== 'OCA\\WorkflowEngine\\Check\\UserGroupMembership') {
-				return;
+			if (check.class !== 'OCA\\WorkflowEngine\\Check\\UserGroupMembership') {
+				return
 			}
 
-			$(element).css('width', '400px');
+			$(element).css('width', '400px')
 
 			$(element).select2({
 				data: { results: groups, text: 'displayname' },
-				initSelection: function (element, callback) {
-					var groupId = element.val();
+				initSelection: function(element, callback) {
+					var groupId = element.val()
 					if (groupId && groups.length > 0) {
 						callback({
 							id: groupId,
-							displayname: groups.find(function (group) {
-								return group.id === groupId;
+							displayname: groups.find(function(group) {
+								return group.id === groupId
 							}).displayname
-						});
+						})
 					} else if (groupId) {
 						callback({
 							id: groupId,
 							displayname: groupId
-						});
+						})
 					} else {
-						callback();
+						callback()
 					}
 				},
-				formatResult: function (element) {
-					return '<span>' + escapeHTML(element.displayname) + '</span>';
+				formatResult: function(element) {
+					return '<span>' + escapeHTML(element.displayname) + '</span>'
 				},
-				formatSelection: function (element) {
-					return '<span title="'+escapeHTML(element.id)+'">'+escapeHTML(element.displayname)+'</span>';
+				formatSelection: function(element) {
+					return '<span title="' + escapeHTML(element.id) + '">' + escapeHTML(element.displayname) + '</span>'
 				}
-			});
+			})
 		}
-	};
-})();
+	}
+})()
 
-OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.UserGroupMembershipPlugin);
+OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.UserGroupMembershipPlugin)
diff --git a/apps/workflowengine/src/services/Operation.js b/apps/workflowengine/src/services/Operation.js
index b2257b5545a..99dca212f4c 100644
--- a/apps/workflowengine/src/services/Operation.js
+++ b/apps/workflowengine/src/services/Operation.js
@@ -13,17 +13,9 @@ const ALL_CHECKS = [
 	'OCA\\WorkflowEngine\\Check\\UserGroupMembership'
 ]
 
-const Entities = OCP.InitialState.loadState('workflowengine', 'entities').map(entity => {
-	return {
-		...entity,
-		// TODO: see if we should have this defined in the backend as well
-		checks: [...ALL_CHECKS]
-	}
-})
-
 const Checks = Object.values(OCA.WorkflowEngine.Plugins).map((plugin) => {
 	if (plugin.component) {
-		return {...plugin.getCheck(), component: plugin.component}
+		return { ...plugin.getCheck(), component: plugin.component }
 	}
 	return plugin.getCheck()
 }).reduce((obj, item) => {
@@ -31,113 +23,55 @@ const Checks = Object.values(OCA.WorkflowEngine.Plugins).map((plugin) => {
 	return obj
 }, {})
 
+const Operators = OCP.InitialState.loadState('workflowengine', 'operators')
+
 /**
- * Register operations
- * TODO: should be provided by the backend
+ * Extend operators for testing
  */
-
-class OperationService {
-
-	constructor() {
-		this.operations = {}
-	}
-	registerOperation (operation) {
-		this.operations[operation.class] = Object.assign({
-			color: 'var(--color-primary)'
-		}, operation)
-	}
-
-	getAll() {
-		return this.operations
-	}
-
-	get(className) {
-		return this.operations[className]
-	}
-
-}
-const operationService = new OperationService()
-
-operationService.registerOperation({
-	class: 'OCA\\FilesAccessControl\\Operation',
-	title: 'Block access',
-	description: 'Deny access to files when they are accessed',
-	icon: 'icon-block',
+Operators['OCA\\FilesAccessControl\\Operation'] = {
+	...Operators['OCA\\FilesAccessControl\\Operation'],
 	color: 'var(--color-error)',
-	entites: [
+	entities: [
 		'OCA\\WorkflowEngine\\Entity\\File'
 	],
-	events: [
-		// TODO: this is probably handled differently since there is no regular event for files access control
-		'OCA\\WorkflowEngine\\Entity\\File::postTouch'
-	],
 	operation: 'deny'
-})
+}
+Operators['OCA\\WorkflowPDFConverter\\Operation'] = {
+	id: 'OCA\\WorkflowPDFConverter\\Operation',
+	name: 'Convert to PDF',
+	description: 'Generate a PDF file',
+	color: '#dc5047',
+	iconClass: 'icon-convert-pdf',
+	options: ConvertToPdf
+}
 
-operationService.registerOperation({
-	class: 'OCA\\TestExample\\Operation1',
-	title: 'Rename file',
+Operators['OCA\\TestExample\\Operation1'] = {
+	id: 'OCA\\TestExample\\Operation1',
+	name: 'Rename file',
 	description: '🚧 For UI mocking only',
-	icon: 'icon-address-white',
+	iconClass: 'icon-address-white',
 	color: 'var(--color-success)',
-	entites: [],
-	events: [],
 	operation: 'deny'
-})
-operationService.registerOperation({
-	class: 'OCA\\TestExample\\Operation2',
-	title: 'Notify me',
+}
+Operators['OCA\\TestExample\\Operation2'] = {
+	id: 'OCA\\TestExample\\Operation2',
+	name: 'Notify me',
 	description: '🚧 For UI mocking only',
-	icon: 'icon-comment-white',
+	iconClass: 'icon-comment-white',
 	color: 'var(--color-warning)',
-	entites: [],
-	events: [],
-	operation: 'deny'
-})
-operationService.registerOperation({
-	class: 'OCA\\TestExample\\Operation3',
-	title: 'Call a web hook',
-	description: '🚧 For UI mocking only',
-	icon: 'icon-category-integration icon-invert',
-	color: 'var(--color-primary)',
-	entites: [],
-	events: [],
 	operation: 'deny'
-})
-
-operationService.registerOperation({
-	class: 'OCA\\FilesAutomatedTagging\\Operation',
-	title: 'Tag a file',
+}
+Operators['OCA\\FilesAutomatedTagging\\Operation'] = {
+	id: 'OCA\\FilesAutomatedTagging\\Operation',
+	name: 'Tag a file',
 	description: 'Assign a tag to a file',
-	icon: 'icon-tag-white',
-	events: [
-		'WorkflowEngine_Entity_File::postWrite',
-		//'WorkflowEngine_Entity_File::postTagged',
-	],
+	iconClass: 'icon-tag-white',
+	color: 'var(--color-primary)',
 	options: Tag
-
-})
-
-operationService.registerOperation({
-	class: 'OCA\\WorkflowPDFConverter\\Operation',
-	title: 'Convert to PDF',
-	description: 'Generate a PDF file',
-	color: '#dc5047',
-	icon: 'icon-convert-pdf',
-	events: [
-		'WorkflowEngine_Entity_File::postWrite',
-		//EVENT_FILE_TAGGED
-	],
-	options: ConvertToPdf
-})
-
-console.debug('[InitialState] Entities', Entities)
-console.debug('[WorkflowEngine] Checks', Checks)
-console.debug('[WorkflowEngine] Operations', operationService.operations)
-
+}
 
 export {
-	Entities,
 	Checks,
-	operationService
+	Operators,
+	ALL_CHECKS
 }
diff --git a/apps/workflowengine/src/templates/operation.handlebars b/apps/workflowengine/src/templates/operation.handlebars
deleted file mode 100644
index 0899890cef2..00000000000
--- a/apps/workflowengine/src/templates/operation.handlebars
+++ /dev/null
@@ -1,45 +0,0 @@
-<div class="operation{{#if hasChanged}} modified{{/if}}">
-	<div class="operation-header">
-		<input type="text" class="operation-name" placeholder="{{shortRuleDescTXT}}" value="{{operation.name}}" />
-		<input type="text" class="operation-operation" value="{{operation.operation}}" />
-		{{! delete only makes sense if the operation is already saved }}
-		{{#if operation.id}}
-			<span class="button-delete icon-delete"></span>
-		{{/if}}
-	</div>
-
-	<div class="checks">
-		{{#each operation.checks}}
-			<div class="check" data-id="{{@index}}">
-				<select class="check-class">
-					{{#each ../classes}}
-						<option value="{{class}}" {{{selectItem class ../class}}}>{{name}}</option>
-					{{/each}}
-				</select>
-				<select class="check-operator">
-					{{#each (getOperators class)}}
-						<option value="{{operator}}" {{{selectItem operator ../operator}}}>{{name}}</option>
-					{{/each}}
-				</select>
-				<input type="text" class="check-value" value="{{value}}">
-				<span class="button-delete-check icon-delete"></span>
-			</div>
-		{{/each}}
-	</div>
-	<button class="button-add">{{addRuleTXT}}</button>
-	{{#if hasChanged}}
-	{{! reset only makes sense if the operation is already saved }}
-		{{#if operation.id}}
-			<button class="button-reset pull-right">{{resetTXT}}</button>
-		{{/if}}
-		<button class="button-save pull-right">{{saveTXT}}</button>
-	{{/if}}
-	{{#if saving}}
-		<span class="icon-loading-small pull-right"></span>
-		<span class="pull-right">{{savingTXT}}</span>
-	{{else}}{{#if message}}
-		<span class="msg pull-right {{#if errorMessage}}error{{else}}success{{/if}}">
-					{{message}}{{#if errorMessage}} {{errorMessage}}{{/if}}
-				</span>
-	{{/if}}{{/if}}
-</div>
diff --git a/apps/workflowengine/src/templates/operations.handlebars b/apps/workflowengine/src/templates/operations.handlebars
deleted file mode 100644
index 14b62ee79a6..00000000000
--- a/apps/workflowengine/src/templates/operations.handlebars
+++ /dev/null
@@ -1,2 +0,0 @@
-<div class="operations"></div>
-<button class="button-add-operation">{{addRuleGroupTXT}}</button>
diff --git a/apps/workflowengine/src/workflowengine.js b/apps/workflowengine/src/workflowengine.js
index 6c7af2a446e..866f049b0bf 100644
--- a/apps/workflowengine/src/workflowengine.js
+++ b/apps/workflowengine/src/workflowengine.js
@@ -1,19 +1,25 @@
-import './filemimetypeplugin'
-import './filenameplugin'
-import './filesizeplugin'
-import './filesystemtagsplugin'
-import './requestremoteaddressplugin'
-import './requesttimeplugin'
-import './requesturlplugin'
-import './requestuseragentplugin'
-import './usergroupmembershipplugin'
+import './legacy/filemimetypeplugin'
+import './legacy/filenameplugin'
+import './legacy/filesizeplugin'
+import './legacy/filesystemtagsplugin'
+import './legacy/requestremoteaddressplugin'
+import './legacy/requesttimeplugin'
+import './legacy/requesturlplugin'
+import './legacy/requestuseragentplugin'
+import './legacy/usergroupmembershipplugin'
 
-window.OCA.WorkflowEngine = OCA.WorkflowEngine
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+import store from './store'
 
-import Vue from 'vue';
+import Settings from './components/Workflow'
 
-Vue.prototype.t = t;
+window.OCA.WorkflowEngine = OCA.WorkflowEngine
+Vue.use(Vuex)
 
-import Settings from './components/Workflow';
+Vue.prototype.t = t
 const View = Vue.extend(Settings)
-new View({}).$mount('#workflowengine')
\ No newline at end of file
+new View({
+	store
+}).$mount('#workflowengine')
-- 
GitLab