Signed-off-by: Julius Härtl <jus@bitgrid.net>tags/v18.0.0beta1
@@ -3,12 +3,17 @@ | |||
<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 :disabled="!currentOption" v-model="currentOperator" :options="operators" | |||
<Multiselect v-model="currentOperator" :disabled="!currentOption" :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" :disabled="!currentOption" :check="check" @valid="valid=true && validate()" @invalid="valid=false && validate()" /> | |||
<input v-else v-model="check.value" type="text" :class="{ invalid: !valid }" | |||
@input="updateCheck" :disabled="!currentOption" :placeholder="valuePlaceholder"> | |||
<component :is="currentOption.component" v-if="currentOperator && currentComponent" v-model="check.value" | |||
:disabled="!currentOption" :check="check" | |||
@input="updateCheck" | |||
@valid="(valid=true) && validate()" | |||
@invalid="(valid=false) && validate()" /> | |||
<input v-else v-model="check.value" type="text" | |||
:class="{ invalid: !valid }" | |||
:disabled="!currentOption" :placeholder="valuePlaceholder" @input="updateCheck"> | |||
<Actions> | |||
<ActionButton v-if="deleteVisible || !currentOption" icon="icon-delete" @click="$emit('remove')" /> | |||
</Actions> | |||
@@ -47,7 +52,7 @@ export default { | |||
currentOption: null, | |||
currentOperator: null, | |||
options: [], | |||
valid: true, | |||
valid: true | |||
} | |||
}, | |||
computed: { | |||
@@ -67,6 +72,12 @@ export default { | |||
if (this.currentOption && this.currentOption.placeholder) { | |||
return this.currentOption.placeholder(this.check) | |||
} | |||
return '' | |||
} | |||
}, | |||
watch: { | |||
'check.operator': function() { | |||
this.validate() | |||
} | |||
}, | |||
mounted() { | |||
@@ -74,11 +85,6 @@ export default { | |||
this.currentOption = this.Checks[this.check.class] | |||
this.currentOperator = this.operators.find((operator) => operator.operator === this.check.operator) | |||
}, | |||
watch: { | |||
'check.operator': function () { | |||
this.validate() | |||
} | |||
}, | |||
methods: { | |||
showDelete() { | |||
this.deleteVisible = true | |||
@@ -88,7 +94,7 @@ export default { | |||
}, | |||
validate() { | |||
if (this.currentOption && this.currentOption.validate) { | |||
if(this.currentOption.validate(this.check)) { | |||
if (this.currentOption.validate(this.check)) { | |||
this.valid = true | |||
} else { | |||
this.valid = false |
@@ -1,35 +1,39 @@ | |||
<template> | |||
<div> | |||
<multiselect | |||
<Multiselect | |||
:value="currentValue" | |||
placeholder="Select a user agent" | |||
:placeholder="t('workflowengine', 'Select a file type')" | |||
label="label" | |||
track-by="pattern" | |||
:options="options" :multiple="false" :tagging="false" @input="setValue"> | |||
:options="options" :multiple="false" :tagging="false" | |||
@input="setValue"> | |||
<template slot="singleLabel" slot-scope="props"> | |||
<span class="option__icon" :class="props.option.icon"></span> | |||
<span class="option__icon" :class="props.option.icon" /> | |||
<span class="option__title option__title_single">{{ props.option.label }}</span> | |||
</template> | |||
<template slot="option" slot-scope="props"> | |||
<span class="option__icon" :class="props.option.icon"></span> | |||
<span class="option__icon" :class="props.option.icon" /> | |||
<span class="option__title">{{ props.option.label }}</span> | |||
</template> | |||
</multiselect> | |||
<input type="text" :value="currentValue.pattern" @input="updateCustom"/> | |||
</Multiselect> | |||
<input type="text" :value="currentValue.pattern" @input="updateCustom" v-if="!isPredefined"> | |||
</div> | |||
</template> | |||
<script> | |||
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect' | |||
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect' | |||
import valueMixin from './../../mixins/valueMixin' | |||
export default { | |||
name: 'FileMimeType', | |||
components: { | |||
Multiselect | |||
}, | |||
mixins: [ | |||
valueMixin | |||
], | |||
data() { | |||
return { | |||
value: '', | |||
predefinedTypes: [ | |||
{ | |||
icon: 'icon-picture', | |||
@@ -53,23 +57,29 @@ export default { | |||
options() { | |||
return [...this.predefinedTypes, this.customValue] | |||
}, | |||
isPredefined() { | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.pattern) | |||
if (matchingPredefined) { | |||
return true | |||
} | |||
return false | |||
}, | |||
customValue() { | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.value.pattern === type.pattern) | |||
return { | |||
icon: 'icon-settings-dark', | |||
label: t('workflowengine', 'Custom pattern'), | |||
pattern: '', | |||
label: t('workflowengine', 'Custom mimetype'), | |||
pattern: '' | |||
} | |||
}, | |||
currentValue() { | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.value === type.pattern) | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.newValue === type.pattern) | |||
if (matchingPredefined) { | |||
return matchingPredefined | |||
} | |||
return { | |||
icon: 'icon-settings-dark', | |||
label: t('workflowengine', 'Custom pattern'), | |||
pattern: this.value, | |||
label: t('workflowengine', 'Custom mimetype'), | |||
pattern: this.newValue | |||
} | |||
} | |||
}, | |||
@@ -79,25 +89,19 @@ export default { | |||
var result = regexRegex.exec(string) | |||
return result !== null | |||
}, | |||
setValue (value) { | |||
setValue(value) { | |||
// TODO: check if value requires a regex and set the check operator according to that | |||
if (value !== null) { | |||
this.value = value.pattern | |||
this.newValue = value.pattern | |||
this.$emit('input', this.newValue) | |||
} | |||
}, | |||
updateCustom (event) { | |||
console.log(event) | |||
this.value = event.target.value | |||
updateCustom(event) { | |||
this.newValue = event.target.value | |||
this.$emit('input', this.newValue) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.multiselect::v-deep .multiselect__single { | |||
display: flex; | |||
} | |||
input, .multiselect { | |||
width: 100%; | |||
} | |||
</style> | |||
<style scoped src="./../../css/multiselect.css"></style> |
@@ -1,68 +0,0 @@ | |||
<!-- | |||
- @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> | |||
- | |||
- @author Julius Härtl <jus@bitgrid.net> | |||
- | |||
- @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/>. | |||
- | |||
--> | |||
<template> | |||
<MultiselectTag v-model="newValue" :multiple="false" type="text" placeholder="1 MB" | |||
@input="update"/> | |||
</template> | |||
<script> | |||
import { MultiselectTag } from 'nextcloud-vue' | |||
export default { | |||
name: 'SizeValue', | |||
components: { | |||
MultiselectTag | |||
}, | |||
props: { | |||
value: { | |||
type: String, | |||
default: '' | |||
} | |||
}, | |||
data() { | |||
return { | |||
valid: false, | |||
newValue: this.value | |||
} | |||
}, | |||
watch: { | |||
value() { | |||
this.newValue = this.value | |||
} | |||
}, | |||
methods: { | |||
update() { | |||
if (this.validate()) { | |||
this.$emit('input', this.newValue) | |||
this.valid = false | |||
} else { | |||
this.valid = false | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
</style> |
@@ -1,14 +1,17 @@ | |||
<template> | |||
<div class="timeslot"> | |||
<multiselect v-model="newValue.timezone" :options="timezones"></multiselect> | |||
<input type="text" class="timeslot--start" v-model="newValue.startTime" placeholder="08:00" @input="update"/> | |||
<input type="text" v-model="newValue.endTime" placeholder="18:00" @input="update"/> | |||
<Multiselect v-model="newValue.timezone" :options="timezones" /> | |||
<input v-model="newValue.startTime" type="text" class="timeslot--start" | |||
placeholder="08:00" @input="update"> | |||
<input v-model="newValue.endTime" type="text" placeholder="18:00" | |||
@input="update"> | |||
</div> | |||
</template> | |||
<script> | |||
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect' | |||
import moment from 'moment-timezone' | |||
import valueMixin from '../../mixins/valueMixin'; | |||
const zones = moment.tz.names() | |||
export default { | |||
@@ -16,6 +19,9 @@ export default { | |||
components: { | |||
Multiselect | |||
}, | |||
mixins: [ | |||
valueMixin | |||
], | |||
props: { | |||
value: { | |||
type: String, | |||
@@ -29,7 +35,7 @@ export default { | |||
startTime: null, | |||
endTime: null, | |||
timezone: moment.tz.guess() | |||
}, | |||
} | |||
} | |||
}, | |||
computed: { | |||
@@ -37,8 +43,8 @@ export default { | |||
return zones | |||
} | |||
}, | |||
watch: { | |||
'value': function(value) { | |||
methods: { | |||
updateInternalValue(value) { | |||
var data = JSON.parse(value) | |||
var startTime = data[0].split(' ', 2)[0] | |||
var endTime = data[1].split(' ', 2)[0] | |||
@@ -48,13 +54,11 @@ export default { | |||
endTime: endTime, | |||
timezone: timezone | |||
} | |||
} | |||
}, | |||
methods: { | |||
}, | |||
validate() { | |||
return this.newValue.startTime && this.newValue.startTime.match(/^(0[0-9]|1[0-9]|2[0-3]|[0-9]):[0-5][0-9]$/i) !== null && | |||
this.newValue.endTime && this.newValue.endTime.match(/^(0[0-9]|1[0-9]|2[0-3]|[0-9]):[0-5][0-9]$/i) !== null && | |||
moment.tz.zone(this.newValue.timezone) !== null | |||
return this.newValue.startTime && this.newValue.startTime.match(/^(0[0-9]|1[0-9]|2[0-3]|[0-9]):[0-5][0-9]$/i) !== null | |||
&& this.newValue.endTime && this.newValue.endTime.match(/^(0[0-9]|1[0-9]|2[0-3]|[0-9]):[0-5][0-9]$/i) !== null | |||
&& moment.tz.zone(this.newValue.timezone) !== null | |||
}, | |||
update() { | |||
if (this.validate()) { |
@@ -22,47 +22,51 @@ | |||
<template> | |||
<div> | |||
<multiselect | |||
<Multiselect | |||
:value="currentValue" | |||
placeholder="Select a file type" | |||
:placeholder="t('workflowengine', 'Select a user agent')" | |||
label="label" | |||
track-by="pattern" | |||
group-values="children", | |||
group-label="text", | |||
:options="options" :multiple="false" :tagging="false" @input="setValue"> | |||
group-values="children" | |||
group-label="label" | |||
:options="options" :multiple="false" :tagging="false" | |||
@input="setValue"> | |||
<template slot="singleLabel" slot-scope="props"> | |||
<span class="option__icon" :class="props.option.icon"></span> | |||
<span class="option__icon" :class="props.option.icon" /> | |||
<span class="option__title option__title_single">{{ props.option.label }}</span> | |||
</template> | |||
<template slot="option" slot-scope="props"> | |||
<span class="option__icon" :class="props.option.icon"></span> | |||
<span class="option__title">{{ props.option.label }}</span> | |||
<span class="option__icon" :class="props.option.icon" /> | |||
<span class="option__title">{{ props.option.label }} {{ props.option.$groupLabel }}</span> | |||
</template> | |||
</multiselect> | |||
<input type="text" :value="currentValue.pattern" @input="updateCustom"/> | |||
</Multiselect> | |||
<input type="text" :value="currentValue.pattern" @input="updateCustom" v-if="!isPredefined"> | |||
</div> | |||
</template> | |||
<script> | |||
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect' | |||
import valueMixin from '../../mixins/valueMixin'; | |||
export default { | |||
name: 'UserAgent', | |||
name: 'RequestUserAgent', | |||
components: { | |||
Multiselect | |||
}, | |||
mixins: [ | |||
valueMixin | |||
], | |||
data() { | |||
return { | |||
value: '', | |||
newValue: '', | |||
predefinedTypes: [ | |||
{ | |||
text: t('workflowengine', 'Sync clients'), | |||
label: 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') } | |||
{ pattern: 'android', label: t('workflowengine', 'Android client'), icon: 'icon-phone' }, | |||
{ pattern: 'ios', label: t('workflowengine', 'iOS client'), icon: 'icon-phone' }, | |||
{ pattern: 'desktop', label: t('workflowengine', 'Desktop client'), icon: 'icon-desktop' }, | |||
{ pattern: 'mail', label: t('workflowengine', 'Thunderbird & Outlook addons'), icon: 'icon-mail' } | |||
] | |||
} | |||
] | |||
@@ -72,23 +76,34 @@ export default { | |||
options() { | |||
return [...this.predefinedTypes, this.customValue] | |||
}, | |||
isPredefined() { | |||
const matchingPredefined = this.predefinedTypes.map(groups => groups.children).flat().find((type) => this.newValue === type.pattern) | |||
if (matchingPredefined) { | |||
return true | |||
} | |||
return false | |||
}, | |||
customValue() { | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.value.pattern === type.pattern) | |||
return { | |||
icon: 'icon-settings-dark', | |||
label: t('workflowengine', 'Custom pattern'), | |||
pattern: '', | |||
label: t('workflowengine', 'Others'), | |||
children: [ | |||
{ | |||
icon: 'icon-settings-dark', | |||
label: t('workflowengine', 'Custom user agent'), | |||
pattern: '' | |||
} | |||
] | |||
} | |||
}, | |||
currentValue() { | |||
const matchingPredefined = this.predefinedTypes.find((type) => this.value === type.pattern) | |||
const matchingPredefined = this.predefinedTypes.map(groups => groups.children).flat().find((type) => this.newValue === type.pattern) | |||
if (matchingPredefined) { | |||
return matchingPredefined | |||
} | |||
return { | |||
icon: 'icon-settings-dark', | |||
label: t('workflowengine', 'Custom pattern'), | |||
pattern: this.value, | |||
label: t('workflowengine', 'Custom user agent'), | |||
pattern: this.newValue, | |||
} | |||
} | |||
}, | |||
@@ -98,25 +113,19 @@ export default { | |||
var result = regexRegex.exec(string) | |||
return result !== null | |||
}, | |||
setValue (value) { | |||
setValue(value) { | |||
// TODO: check if value requires a regex and set the check operator according to that | |||
if (value !== null) { | |||
this.value = value.pattern | |||
this.newValue = value.pattern | |||
this.$emit('input', this.newValue) | |||
} | |||
}, | |||
updateCustom (event) { | |||
console.log(event) | |||
this.value = event.target.value | |||
updateCustom(event) { | |||
this.newValue = event.target.value | |||
this.$emit('input', this.newValue) | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.multiselect::v-deep .multiselect__single { | |||
display: flex; | |||
} | |||
input, .multiselect { | |||
width: 100%; | |||
} | |||
</style> | |||
<style scoped src="./../../css/multiselect.css"></style> |
@@ -20,8 +20,8 @@ | |||
* | |||
*/ | |||
import FileMimeType from './FileMimeType'; | |||
import { stringValidator, validateIPv4, validateIPv6} from './../../helpers/validators' | |||
import FileMimeType from './FileMimeType' | |||
import { stringValidator, validateIPv4, validateIPv6 } from './../../helpers/validators' | |||
const FileChecks = [ | |||
{ | |||
class: 'OCA\\WorkflowEngine\\Check\\FileName', | |||
@@ -77,7 +77,7 @@ const FileChecks = [ | |||
], | |||
placeholder: (check) => { | |||
if (check.operator === 'matchesIPv6' || check.operator === '!matchesIPv6') { | |||
return '::1/128'; | |||
return '::1/128' | |||
} | |||
return '127.0.0.1/32' | |||
}, |
@@ -20,8 +20,8 @@ | |||
* | |||
*/ | |||
import RequestUserAgent from './RequestUserAgent'; | |||
import RequestTime from './RequestTime'; | |||
import RequestUserAgent from './RequestUserAgent' | |||
import RequestTime from './RequestTime' | |||
const RequestChecks = [ | |||
{ | |||
@@ -32,7 +32,7 @@ const RequestChecks = [ | |||
{ operator: '!is', name: t('workflowengine', 'is not') }, | |||
{ operator: 'matches', name: t('workflowengine', 'matches') }, | |||
{ operator: '!matches', name: t('workflowengine', 'does not match') } | |||
], | |||
] | |||
// TODO: implement component | |||
}, | |||
{ | |||
@@ -53,8 +53,7 @@ const RequestChecks = [ | |||
{ operator: 'matches', name: t('workflowengine', 'matches') }, | |||
{ operator: '!matches', name: t('workflowengine', 'does not match') } | |||
], | |||
// TODO: implement component | |||
// component: RequestUserAgent | |||
component: RequestUserAgent | |||
}, | |||
{ | |||
class: 'OCA\\WorkflowEngine\\Check\\UserGroupMembership', | |||
@@ -62,7 +61,7 @@ const RequestChecks = [ | |||
operators: [ | |||
{ operator: 'is', name: t('workflowengine', 'is member of') }, | |||
{ operator: '!is', name: t('workflowengine', 'is not member of') } | |||
], | |||
] | |||
// TODO: implement component | |||
} | |||
] |
@@ -2,8 +2,8 @@ | |||
<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})` }" /> | |||
<div class="actions__item__description"> | |||
<h3>{{ operation.name }}</h3> | |||
<small>{{ operation.description }}</small> | |||
<h3>{{ operation.name }}</h3> | |||
<small>{{ operation.description }}</small> | |||
</div> | |||
<div class="actions__item_options"> | |||
<slot /> |
@@ -5,9 +5,10 @@ | |||
<span>{{ t('workflowengine', 'When') }}</span> | |||
<Event :rule="rule" @update="updateRule" /> | |||
</p> | |||
<p v-for="check in rule.checks"> | |||
<p v-for="(check, index) in rule.checks" :key="index"> | |||
<span>{{ t('workflowengine', 'and') }}</span> | |||
<Check :check="check" :rule="rule" @update="updateRule" @remove="removeCheck(check)" /> | |||
<Check :check="check" :rule="rule" @update="updateRule" | |||
@remove="removeCheck(check)" /> | |||
</p> | |||
<p> | |||
<span /> | |||
@@ -15,7 +16,7 @@ | |||
value="Add a new filter" @click="rule.checks.push({class: null, operator: null, value: null})"> | |||
</p> | |||
</div> | |||
<div class="flow-icon icon-confirm"></div> | |||
<div class="flow-icon icon-confirm" /> | |||
<div class="action"> | |||
<div class="buttons"> | |||
<Actions> | |||
@@ -32,7 +33,7 @@ | |||
@input="updateOperation" /> | |||
</Operation> | |||
<button v-tooltip="ruleStatus.tooltip" class="status-button icon" :class="ruleStatus.class" | |||
@click="saveRule"> | |||
@click="saveRule"> | |||
{{ ruleStatus.title }} | |||
</button> | |||
</div> | |||
@@ -245,5 +246,4 @@ export default { | |||
} | |||
} | |||
</style> |
@@ -20,7 +20,6 @@ | |||
* | |||
*/ | |||
const validateRegex = function(string) { | |||
var regexRegex = /^\/(.*)\/([gui]{0,3})$/ | |||
var result = regexRegex.exec(string) |
@@ -1,78 +0,0 @@ | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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/>. | |||
* | |||
*/ | |||
(function() { | |||
OCA.WorkflowEngine = OCA.WorkflowEngine || {} | |||
OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {} | |||
OCA.WorkflowEngine.Plugins.FileSystemTagsPlugin = { | |||
getCheck: function() { | |||
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') } | |||
] | |||
} | |||
}, | |||
render: function(element, check) { | |||
if (check.class !== 'OCA\\WorkflowEngine\\Check\\FileSystemTags') { | |||
return | |||
} | |||
$(element).css('width', '400px') | |||
$(element).select2({ | |||
allowClear: false, | |||
multiple: false, | |||
placeholder: t('workflowengine', 'Select tag…'), | |||
query: _.debounce(function(query) { | |||
query.callback({ | |||
results: OC.SystemTags.collection.filterByName(query.term) | |||
}) | |||
}, 100, true), | |||
id: function(element) { | |||
return element.get('id') | |||
}, | |||
initSelection: function(element, callback) { | |||
callback($(element).val()) | |||
}, | |||
formatResult: function(tag) { | |||
return OC.SystemTags.getDescriptiveTag(tag) | |||
}, | |||
formatSelection: function(tagId) { | |||
var tag = OC.SystemTags.collection.get(tagId) | |||
if (!_.isUndefined(tag)) { | |||
return OC.SystemTags.getDescriptiveTag(tag) | |||
} | |||
}, | |||
escapeMarkup: function(m) { | |||
return m | |||
} | |||
}) | |||
} | |||
} | |||
})() | |||
OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.FileSystemTagsPlugin) |
@@ -1,196 +0,0 @@ | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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/>. | |||
* | |||
*/ | |||
(function() { | |||
OCA.WorkflowEngine = OCA.WorkflowEngine || {} | |||
OCA.WorkflowEngine.Plugins = OCA.WorkflowEngine.Plugins || {} | |||
OCA.WorkflowEngine.Plugins.RequestTimePlugin = { | |||
timezones: [ | |||
'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') } | |||
] | |||
} | |||
}, | |||
render: function(element, check) { | |||
if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestTime') { | |||
return | |||
} | |||
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) | |||
var splittedStart = value[0].split(' ', 2) | |||
var splittedEnd = value[1].split(' ', 2) | |||
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) | |||
} | |||
$element.css('display', 'none') | |||
$('<input>') | |||
.attr('type', 'text') | |||
.attr('placeholder', t('workflowengine', 'Start')) | |||
.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: '16:00' })) | |||
.addClass('has-tooltip') | |||
.tooltip({ | |||
placement: 'bottom' | |||
}) | |||
.addClass('start') | |||
.val(startTime) | |||
.insertBefore($element) | |||
$('<input>') | |||
.attr('type', 'text') | |||
.attr('placeholder', t('workflowengine', 'End')) | |||
.attr('title', t('workflowengine', 'Example: {placeholder}', { placeholder: '16:00' })) | |||
.addClass('has-tooltip') | |||
.tooltip({ | |||
placement: 'bottom' | |||
}) | |||
.addClass('end') | |||
.val(endTime) | |||
.insertBefore($element) | |||
var timezoneInput = $('<input>') | |||
.attr('type', 'hidden') | |||
.css('width', '250px') | |||
.insertBefore($element) | |||
.val(timezone) | |||
timezoneInput.select2({ | |||
allowClear: false, | |||
multiple: false, | |||
placeholder: t('workflowengine', 'Select timezone…'), | |||
ajax: { | |||
url: OC.generateUrl('apps/workflowengine/timezones'), | |||
dataType: 'json', | |||
quietMillis: 100, | |||
data: function(term) { | |||
if (term === '') { | |||
// Default search in the same continent... | |||
term = jstz.determine().name().split('/') | |||
term = term[0] | |||
} | |||
return { | |||
search: term | |||
} | |||
}, | |||
results: function(response) { | |||
var results = [] | |||
$.each(response, function(timezone) { | |||
results.push({ id: timezone }) | |||
}) | |||
return { | |||
results: results, | |||
more: false | |||
} | |||
} | |||
}, | |||
initSelection: function(element, callback) { | |||
callback(element.val()) | |||
}, | |||
formatResult: function(element) { | |||
return '<span>' + element.id + '</span>' | |||
}, | |||
formatSelection: function(element) { | |||
if (!_.isUndefined(element.id)) { | |||
element = element.id | |||
} | |||
return '<span>' + element + '</span>' | |||
} | |||
}) | |||
// Has to be added after select2 for `event.target.classList` | |||
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)) | |||
this._$element = $element | |||
}, | |||
update: function(event) { | |||
var value = event.target.value | |||
var key = null | |||
for (var i = 0; i < event.target.classList.length; i++) { | |||
key = event.target.classList[i] | |||
} | |||
if (key === null) { | |||
console.warn('update triggered but element doesn\'t have any class') | |||
return | |||
} | |||
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') | |||
if (parsedDate === 'Invalid date') { | |||
return | |||
} | |||
var indexValue = 0 | |||
if (key === 'end') { | |||
indexValue = 1 | |||
} | |||
data[indexValue] = parsedDate + ' ' + timezone | |||
} | |||
if (key === 'timezone') { | |||
data[0] = startTime.format('HH:mm') + ' ' + value | |||
data[1] = endTime.format('HH:mm') + ' ' + value | |||
} | |||
this._$element.val(JSON.stringify(data)) | |||
this._$element.trigger('change') | |||
} | |||
} | |||
})() | |||
OC.Plugins.register('OCA.WorkflowEngine.CheckPlugins', OCA.WorkflowEngine.Plugins.RequestTimePlugin) |
@@ -1,116 +0,0 @@ | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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/>. | |||
* | |||
*/ | |||
(function() { | |||
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') } | |||
] | |||
} | |||
}, | |||
render: function(element, check) { | |||
if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestURL') { | |||
return | |||
} | |||
var placeholder = 'https://localhost/index.php' | |||
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 })) | |||
.addClass('has-tooltip') | |||
.tooltip({ | |||
placement: 'bottom' | |||
}) | |||
if (check.operator === 'matches' || check.operator === '!matches') { | |||
if (this._validateRegex(check.value)) { | |||
$(element).removeClass('invalid-input') | |||
} else { | |||
$(element).addClass('invalid-input') | |||
} | |||
} else { | |||
var self = this | |||
var data = [ | |||
{ | |||
text: t('workflowengine', 'Predefined URLs'), | |||
children: [ | |||
{ id: 'webdav', text: t('workflowengine', 'Files WebDAV') } | |||
] | |||
} | |||
] | |||
if (this.predefinedValues.indexOf(check.value) === -1) { | |||
data.unshift({ | |||
id: check.value, | |||
text: check.value | |||
}) | |||
} | |||
$(element).select2({ | |||
data: data, | |||
createSearchChoice: function(term) { | |||
if (self.predefinedValues.indexOf(check.value) === -1) { | |||
return { | |||
id: term, | |||
text: term | |||
} | |||
} | |||
}, | |||
id: function(element) { | |||
return element.id | |||
}, | |||
formatResult: function(tag) { | |||
return tag.text | |||
}, | |||
formatSelection: function(tag) { | |||
return tag.text | |||
}, | |||
escapeMarkup: function(m) { | |||
return m | |||
} | |||
}) | |||
} | |||
}, | |||
_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.RequestURLPlugin) |
@@ -1,119 +0,0 @@ | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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/>. | |||
* | |||
*/ | |||
(function() { | |||
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') } | |||
] | |||
} | |||
}, | |||
render: function(element, check) { | |||
if (check.class !== 'OCA\\WorkflowEngine\\Check\\RequestUserAgent') { | |||
return | |||
} | |||
var placeholder = 'Mozilla/5.0 User Agent' | |||
if (check.operator === 'matches' || check.operator === '!matches') { | |||
placeholder = '/^Mozilla\\/5\\.0 (.*)$/i' | |||
} | |||
$(element).css('width', '250px') | |||
.attr('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') | |||
} else { | |||
$(element).addClass('invalid-input') | |||
} | |||
} else { | |||
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') } | |||
] | |||
} | |||
] | |||
if (this.predefinedValues.indexOf(check.value) === -1) { | |||
data.unshift({ | |||
id: check.value, | |||
text: check.value | |||
}) | |||
} | |||
$(element).select2({ | |||
data: data, | |||
createSearchChoice: function(term) { | |||
if (self.predefinedValues.indexOf(check.value) === -1) { | |||
return { | |||
id: term, | |||
text: term | |||
} | |||
} | |||
}, | |||
id: function(element) { | |||
return element.id | |||
}, | |||
formatResult: function(tag) { | |||
return tag.text | |||
}, | |||
formatSelection: function(tag) { | |||
return tag.text | |||
}, | |||
escapeMarkup: function(m) { | |||
return m | |||
} | |||
}) | |||
} | |||
}, | |||
_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.RequestUserAgentPlugin) |
@@ -1,75 +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/>. | |||
* | |||
*/ | |||
(function() { | |||
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') } | |||
] | |||
} | |||
}, | |||
render: function(element, check, groups) { | |||
if (check.class !== 'OCA\\WorkflowEngine\\Check\\UserGroupMembership') { | |||
return | |||
} | |||
$(element).css('width', '400px') | |||
$(element).select2({ | |||
data: { results: groups, text: 'displayname' }, | |||
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 | |||
}) | |||
} else if (groupId) { | |||
callback({ | |||
id: groupId, | |||
displayname: groupId | |||
}) | |||
} else { | |||
callback() | |||
} | |||
}, | |||
formatResult: function(element) { | |||
return '<span>' + 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) |
@@ -85,7 +85,7 @@ const store = new Vuex.Store({ | |||
let events = [] | |||
if (rule.isComplex === false && rule.fixedEntity === '') { | |||
entity = context.state.entities.find((item) => rule.entities && rule.entities[0] === item.id) | |||
entity = entity ? entity : Object.values(context.state.entities)[0] | |||
entity = entity || Object.values(context.state.entities)[0] | |||
events = [entity.events[0].eventName] | |||
} | |||
@@ -124,7 +124,7 @@ const store = new Vuex.Store({ | |||
await axios.delete(getApiUrl(`/${rule.id}`)) | |||
context.commit('removeRule', rule) | |||
}, | |||
setValid (context, { rule, valid }) { | |||
setValid(context, { rule, valid }) { | |||
rule.valid = valid | |||
context.commit('updateRule', rule) | |||
} |