diff options
author | Julius Härtl <jus@bitgrid.net> | 2019-08-19 17:13:33 +0200 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2019-09-10 09:01:23 +0200 |
commit | 9f8ccf1036ff18d961949bfb644c9d445caa8a23 (patch) | |
tree | 5f8e4654ddbdce95cf66f0ed6ef602d312fbe5ba /apps/workflowengine | |
parent | aed630ac0a63771c7a217a3c1d400a354929fafe (diff) | |
download | nextcloud-server-9f8ccf1036ff18d961949bfb644c9d445caa8a23.tar.gz nextcloud-server-9f8ccf1036ff18d961949bfb644c9d445caa8a23.zip |
Use entity/event definitions from backend
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'apps/workflowengine')
-rw-r--r-- | apps/workflowengine/src/components/Check.vue | 16 | ||||
-rw-r--r-- | apps/workflowengine/src/components/Event.vue | 24 | ||||
-rw-r--r-- | apps/workflowengine/src/components/Operation.vue | 25 | ||||
-rw-r--r-- | apps/workflowengine/src/components/Rule.vue | 8 | ||||
-rw-r--r-- | apps/workflowengine/src/components/Workflow.vue | 21 | ||||
-rw-r--r-- | apps/workflowengine/src/services/Operation.js | 168 |
6 files changed, 141 insertions, 121 deletions
diff --git a/apps/workflowengine/src/components/Check.vue b/apps/workflowengine/src/components/Check.vue index c8c7c46aa87..8cfe5a89020 100644 --- a/apps/workflowengine/src/components/Check.vue +++ b/apps/workflowengine/src/components/Check.vue @@ -15,6 +15,7 @@ </template> <script> + import { Checks } from '../services/Operation'; import { Multiselect, Actions, ActionButton } from 'nextcloud-vue' import ClickOutside from 'vue-click-outside'; @@ -43,13 +44,8 @@ } }, mounted() { - this.options = Object.values(OCA.WorkflowEngine.Plugins).map((plugin) => { - if (plugin.component) { - return {...plugin.getCheck(), component: plugin.component} - } - return plugin.getCheck() - }) - this.currentOption = this.options.find((option) => option.class === this.check.class) + 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() @@ -59,12 +55,12 @@ operators() { if (!this.currentOption) return [] - return this.options.find((item) => item.class === this.currentOption.class).operators + return Checks[this.currentOption.class].operators }, currentComponent() { if (!this.currentOption) return [] - let currentComponent = this.options.find((item) => item.class === this.currentOption.class).component + let currentComponent = Checks[this.currentOption.class].component return currentComponent && currentComponent() } }, @@ -101,4 +97,4 @@ ::placeholder { font-size: 10px; } -</style>
\ No newline at end of file +</style> diff --git a/apps/workflowengine/src/components/Event.vue b/apps/workflowengine/src/components/Event.vue index fd5097cecfc..caf5c7631bd 100644 --- a/apps/workflowengine/src/components/Event.vue +++ b/apps/workflowengine/src/components/Event.vue @@ -2,11 +2,11 @@ <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"> - <span class="option__icon" :class="props.option.icon"></span> + <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"> - <span class="option__icon" :class="props.option.icon"></span> + <img class="option__icon" :src="props.option.icon" /> <span class="option__title">{{ props.option.name }}</span> </template> </Multiselect> @@ -15,7 +15,7 @@ <script> import { Multiselect } from 'nextcloud-vue' - import { eventService, operationService } from '../services/Operation' + import { Entities, operationService } from '../services/Operation' export default { name: "Event", @@ -36,7 +36,21 @@ return this.allEvents.find(event => event.id === this.rule.event) }, allEvents() { - return this.operation.events.map((eventName) => eventService.get(eventName)) + 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, + event: eventName, + name: Event.displayName, + icon: Entity.icon, + checks: Entity.checks, + } + }) }, operation() { return operationService.get(this.rule.class) @@ -81,4 +95,4 @@ .option__title_single { font-weight: 900; } -</style>
\ No newline at end of file +</style> diff --git a/apps/workflowengine/src/components/Operation.vue b/apps/workflowengine/src/components/Operation.vue index f7a8f56cede..3e5de3198ca 100644 --- a/apps/workflowengine/src/components/Operation.vue +++ b/apps/workflowengine/src/components/Operation.vue @@ -39,8 +39,8 @@ margin-left: -1px; padding: 10px; border-radius: var(--border-radius-large); - max-width: 230px; margin-right: 20px; + margin-bottom: 20px; } .icon { display: block; @@ -64,20 +64,21 @@ small { font-size: 10pt; } - .icon-block { - background-image: url(/apps-extra/files_accesscontrol/img/app-dark.svg); - } - - .icon-convert-pdf { - background-image: url(/apps-extra/workflow_pdf_converter/img/app-dark.svg); - } .colored { - .icon { - filter: invert(1); - } * { color: var(--color-primary-text) } } -</style>
\ No newline at end of file + + /* TODO: those should be provided by the backend, remove once ready */ + .icon-block { + background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8' standalone='no'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' height='32' width='32' version='1.1' viewBox='0 0 32 32'%3E%3Cpath fill='%23fff' d='m10.203 2-8.203 8.203v11.594l8.203 8.203h11.594l8.203-8.203v-11.594l-8.203-8.203h-11.594zm11.097 5.3092 3.345 3.3448-5.346 5.346 5.346 5.346-3.299 3.299-5.346-5.346-5.346 5.346-3.2992-3.299 5.3462-5.346-5.3462-5.346 3.2992-3.2992 5.346 5.3462 5.3-5.3918z'/%3E%3C/svg%3E"); + } + .icon-convert-pdf { + background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' version='1.1' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23fff'%3E%3Cpath d='m7.0624 2.9056c-0.20526 0-0.36653 0.14989-0.36653 0.34066v8.8571c0 0.19077 0.16127 0.34066 0.36653 0.34066h8.0637c0.20526 0 0.36653-0.14989 0.36653-0.34066v-7.1538l-2.1992-2.044zm4.2518 2.6571s0.05132 0.64725-0.10996 1.567c0.52414 1.3987 1.0996 1.5875 1.3562 1.7033 0.54247-0.040873 1.1472-0.068129 1.6861 0.2044 0.36653 0.19486 0.65536 1.022-0.21992 1.022-0.39586-0.023161-1.1267-0.23574-1.6494-0.47692-0.78145 0.081762-1.752 0.21802-2.5657 0.54505-0.91633 1.4308-1.3268 1.6352-1.6494 1.6352-0.89067-0.21802-0.41052-1.3149-0.073304-1.4989 0.40319-0.32022 0.87601-0.50417 1.0263-0.54505 0.065969-0.10221 1.0146-1.8327 1.2462-2.5549-0.21992-0.69767-0.27123-1.4349-0.14661-1.8736 0.57179-0.69358 1.0996-0.23846 1.0996 0.27253zm-0.51315 2.1121c-0.19793 0.72015-0.98817 2.1012-0.95299 2.044 0.81004-0.33044 1.5394-0.42923 2.3458-0.54505-0.38559-0.16011-0.84009-0.17033-1.3928-1.4989z' stroke-width='.70672'/%3E%3Cpath d='m16.246-9.7651c-2.05e-4 0.0144-6e-3 0.027629-6e-3 0.042066-0.0044 2.2592 2.0761 3.742 4.0564 3.6477v1.2349l2.3737-2.2265-2.3377-2.3407-3e-3 1.2289c-1.0287 0.1337-1.8811-0.66867-1.8659-1.5414 2.9e-4 -0.016152 0.0083-0.029062 9e-3 -0.045071z' stroke-width='.67694'/%3E%3Cpath d='m3.2734 5.1094v1.4492h-2.7676v2.5h2.7246l-0.0019532 1.4629 3.0996-2.6387-3.0547-2.7734z'/%3E%3Cpath d='m8.334-11.356c-0.78035-0.78051-1.9205-1.0863-2.9866-0.80073a0.51533 0.51533 0 1 0 0.26293 0.99405c0.71208-0.19075 1.4702 0.01747 1.9914 0.53876 0.46076 0.46083 0.65567 1.1026 0.56688 1.7376a0.61838 0.61838 0 1 0-0.87225 0.87442l0.8687 0.86886a0.61838 0.61838 0 0 0 0.86992 7.91e-5l0.86886-0.8687a0.61838 0.61838 0 0 0 0.0011543-0.88702 0.61838 0.61838 0 0 0-0.67634-0.12303c0.04094-0.86013-0.27221-1.7117-0.89472-2.3343zm-3.3067 1.0814a0.61838 0.61838 0 0 0-0.015967-0.01364l-0.86984-0.87a0.61838 0.61838 0 0 0-0.042126-0.04213 0.61838 0.61838 0 0 0-0.82551 0.04205l-0.87 0.86984a0.61838 0.61838 0 0 0 0.66145 1.0237c-0.024276 0.84049 0.29182 1.6675 0.90045 2.2762 0.78035 0.78052 1.9205 1.0863 2.9866 0.80073a0.51533 0.51533 0 1 0-0.27202-0.99408c-0.71208 0.19075-1.4669-0.011716-1.988-0.53306-0.45484-0.45491-0.65183-1.0905-0.57258-1.7183l0.018216 0.018221a0.61843 0.61843 0 0 0 0.88935-0.85959z' stroke-width='.68342'/%3E%3Cpath d='m31.219 0.33675v0.00113h-6.9286v1.3295l6.9286 0.036145c0.0026-1.821e-4 0.0053 2.074e-4 0.0079 0 0.0053-4.166e-4 0.01058-0.00137 0.01581-0.00113 0.65203-0.00106 1.1749 0.44619 1.1867 1.0392 0.0108 0.5673-0.60099 1.0888-1.3381 1.0019l-0.0013-0.79858-1.6753 1.5203 1.7016 1.4481-0.0013-0.8031c1.419 0.06127 2.9112-0.90236 2.9081-2.3709-0.0029-1.3197-1.2547-2.4007-2.7961-2.4014-0.0023-1e-6 -0.0043-0.00113-0.0066-0.00113z' stroke-width='.462'/%3E%3Crect x='31.116' y='-1.6777' width='4.3279' height='7.5909'/%3E%3C/g%3E%3C/svg%3E"); + } + .icon-invert { + filter: invert(1); + } +</style> diff --git a/apps/workflowengine/src/components/Rule.vue b/apps/workflowengine/src/components/Rule.vue index 818e15610fa..43cbbced209 100644 --- a/apps/workflowengine/src/components/Rule.vue +++ b/apps/workflowengine/src/components/Rule.vue @@ -163,10 +163,12 @@ .rule { display: flex; + flex-wrap: wrap; + .trigger, .action { flex-grow: 1; min-height: 100px; - width: 50%; + flex-basis: 50%; } .action { position: relative; @@ -177,6 +179,8 @@ } .icon-confirm { background-position: right center; + padding-right: 20px; + margin-right: 20px; } } .trigger p, .action p { @@ -206,4 +210,4 @@ text-align: left; font-size: 1em; } -</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 9993b328827..918236ead84 100644 --- a/apps/workflowengine/src/components/Workflow.vue +++ b/apps/workflowengine/src/components/Workflow.vue @@ -14,12 +14,6 @@ {{ showMoreOperations ? t('workflowengine', 'Show less') : t('workflowengine', 'Show more') }} </button> </div> - <transition name="slide"> - <div class="actions" v-if="!hasUnsavedRule && showMoreOperations && hasMoreOperations"> - <Operation v-for="operation in getMoreOperations" :key="operation.class" :icon="operation.icon" :title="operation.title" :description="operation.description" - @click.native="createNewRule(operation)"></Operation> - </div> - </transition> </div> <transition-group name="slide"> @@ -59,6 +53,9 @@ 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() { @@ -95,10 +92,16 @@ </script> <style scoped lang="scss"> + .section { + max-width: 100vw; + } .actions { display: flex; - .action__item { - border: 1px solid var(--color-border); + flex-wrap: wrap; + .actions__item { + max-width: 300px; + min-width: 200px; + flex-basis: 200px; } } @@ -143,4 +146,4 @@ overflow: hidden; max-height: 0; } -</style>
\ No newline at end of file +</style> diff --git a/apps/workflowengine/src/services/Operation.js b/apps/workflowengine/src/services/Operation.js index 1de7d2a95ad..a24d97ef226 100644 --- a/apps/workflowengine/src/services/Operation.js +++ b/apps/workflowengine/src/services/Operation.js @@ -1,5 +1,41 @@ import ConvertToPdf from './../components/Operations/ConvertToPdf' import Tag from './../components/Operations/Tag' + +const ALL_CHECKS = [ + 'OCA\\WorkflowEngine\\Check\\FileMimeType', + 'OCA\\WorkflowEngine\\Check\\FileName', + 'OCA\\WorkflowEngine\\Check\\FileSize', + 'OCA\\WorkflowEngine\\Check\\FileSystemTags', + 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress', + 'OCA\\WorkflowEngine\\Check\\RequestTime', + 'OCA\\WorkflowEngine\\Check\\RequestURL', + 'OCA\\WorkflowEngine\\Check\\RequestUserAgent', + '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() +}).reduce((obj, item) => { + obj[item.class] = item + return obj +}, {}) + +/** + * Register operations + * TODO: should be provided by the backend + */ + class OperationService { constructor() { @@ -20,92 +56,63 @@ class OperationService { } } - -class EventService { - - constructor() { - this.events = {} - } - registerEvent(event) { - this.events[event.id] = event - } - - getAll() { - return this.events - } - - get(id) { - return this.events[id] - } - -} - const operationService = new OperationService() -const eventService = new EventService() - - -const ALL_CHECKS = [ - 'OCA\\WorkflowEngine\\Check\\FileMimeType', - 'OCA\\WorkflowEngine\\Check\\FileName', - 'OCA\\WorkflowEngine\\Check\\FileSize', - 'OCA\\WorkflowEngine\\Check\\FileSystemTags', - 'OCA\\WorkflowEngine\\Check\\RequestRemoteAddress', - 'OCA\\WorkflowEngine\\Check\\RequestTime', - 'OCA\\WorkflowEngine\\Check\\RequestURL', - 'OCA\\WorkflowEngine\\Check\\RequestUserAgent', - 'OCA\\WorkflowEngine\\Check\\UserGroupMembership' -] - -/** - * TODO: move to separate apps - * TODO: fetch from initial state api - **/ -const EVENT_FILE_ACCESS = 'EVENT_FILE_ACCESS' -const EVENT_FILE_CHANGED = 'EVENT_FILE_CHANGED' -const EVENT_FILE_TAGGED = 'EVENT_FILE_TAGGED' - -eventService.registerEvent({ - id: EVENT_FILE_ACCESS, - name: 'File is accessed', - icon: 'icon-desktop', - checks: ALL_CHECKS, -}) - -eventService.registerEvent({ - id: EVENT_FILE_CHANGED, - name: 'File was updated', - icon: 'icon-folder', - checks: ALL_CHECKS, -}) - - -eventService.registerEvent({ - id: EVENT_FILE_TAGGED, - name: 'File was tagged', - icon: 'icon-tag', - checks: ALL_CHECKS, -}) operationService.registerOperation({ class: 'OCA\\FilesAccessControl\\Operation', title: 'Block access', - description: 'todo', + description: 'Deny access to files when they are accessed', icon: 'icon-block', color: 'var(--color-error)', + entites: [ + 'WorkflowEngine_Entity_File' + ], events: [ - EVENT_FILE_ACCESS + // TODO: this is probably handled differently since there is no regular event for files access control + 'WorkflowEngine_Entity_File::postTouch' ], operation: 'deny' }) operationService.registerOperation({ + class: 'OCA\\TestExample\\Operation1', + title: 'Rename file', + description: '🚧 For UI mocking only', + icon: 'icon-address-white', + color: 'var(--color-success)', + entites: [], + events: [], + operation: 'deny' +}) +operationService.registerOperation({ + class: 'OCA\\TestExample\\Operation2', + title: 'Notify me', + description: '🚧 For UI mocking only', + icon: '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', - description: 'todo', - icon: 'icon-tag', + description: 'Assign a tag to a file', + icon: 'icon-tag-white', events: [ - EVENT_FILE_CHANGED, - EVENT_FILE_TAGGED + 'WorkflowEngine_Entity_File::postWrite', + //'WorkflowEngine_Entity_File::postTagged', ], options: Tag @@ -114,28 +121,23 @@ operationService.registerOperation({ operationService.registerOperation({ class: 'OCA\\WorkflowPDFConverter\\Operation', title: 'Convert to PDF', - description: 'todo', + description: 'Generate a PDF file', color: '#dc5047', icon: 'icon-convert-pdf', events: [ - EVENT_FILE_CHANGED, + '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) -const legacyChecks = Object.values(OCA.WorkflowEngine.Plugins).map((plugin) => { - if (plugin.component) { - return {...plugin.getCheck(), component: plugin.component} - } - return plugin.getCheck() -}).reduce((obj, item) => { - obj[item.class] = item - return obj -}, {}) export { - eventService, + Entities, + Checks, operationService -}
\ No newline at end of file +} |