Merge pull request #17506 from nextcloud/bugfix/12790/workflow-frontend
Workflow frontend polishing
This commit is contained in:
commit
64bfd4bbeb
|
@ -25,5 +25,6 @@ return [
|
||||||
],
|
],
|
||||||
'ocs-resources' => [
|
'ocs-resources' => [
|
||||||
'global_workflows' => ['url' => '/api/v1/workflows/global'],
|
'global_workflows' => ['url' => '/api/v1/workflows/global'],
|
||||||
|
'user_workflows' => ['url' => '/api/v1/workflows/user'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
.workflowengine {
|
|
||||||
.pull-right {
|
|
||||||
float: right
|
|
||||||
}
|
|
||||||
|
|
||||||
.invalid-input {
|
|
||||||
border-color: var(--color-error);
|
|
||||||
}
|
|
||||||
|
|
||||||
.operation {
|
|
||||||
padding: 5px 5px 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-bottom: var(--color-border) 1px solid;
|
|
||||||
border-left: rgba(0, 0, 0, 0) 2px solid;
|
|
||||||
|
|
||||||
&.modified {
|
|
||||||
border-left: var(--color-warning) 2px solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.info {
|
|
||||||
padding: 7px;
|
|
||||||
color: var(--color-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg {
|
|
||||||
border-radius: 3px;
|
|
||||||
margin: 3px 3px 3px 0;
|
|
||||||
padding: 5px;
|
|
||||||
transition: opacity .5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.check {
|
|
||||||
padding-left: 5px;
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--color-background-dark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-delete,
|
|
||||||
.button-delete-check {
|
|
||||||
opacity: 0.5;
|
|
||||||
padding: 11px;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
opacity: 1;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rules {
|
|
||||||
.icon-loading-small {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.operation:nth-last-child(2) {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.operation-header {
|
|
||||||
display: flex;
|
|
||||||
margin-left: 5px;
|
|
||||||
|
|
||||||
.operation-name {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
align-self: flex-start;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-container {
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-delete {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#workflowengine .multiselect .multiselect__single {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workflowengine .option__icon {
|
|
||||||
min-width: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workflowengine input,
|
|
||||||
#workflowengine .multiselect {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -79,8 +79,8 @@ class UserWorkflowsController extends AWorkflowController {
|
||||||
* @throws OCSBadRequestException
|
* @throws OCSBadRequestException
|
||||||
* @throws OCSForbiddenException
|
* @throws OCSForbiddenException
|
||||||
*/
|
*/
|
||||||
public function create(string $class, string $name, array $checks, string $operation): DataResponse {
|
public function create(string $class, string $name, array $checks, string $operation, string $entity, array $events): DataResponse {
|
||||||
return parent::create($class, $name, $checks, $operation);
|
return parent::create($class, $name, $checks, $operation, $entity, $events);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,8 +88,8 @@ class UserWorkflowsController extends AWorkflowController {
|
||||||
* @throws OCSBadRequestException
|
* @throws OCSBadRequestException
|
||||||
* @throws OCSForbiddenException
|
* @throws OCSForbiddenException
|
||||||
*/
|
*/
|
||||||
public function update(int $id, string $name, array $checks, string $operation): DataResponse {
|
public function update(int $id, string $name, array $checks, string $operation, string $entity, array $events): DataResponse {
|
||||||
return parent::update($id, $name, $checks, $operation);
|
return parent::update($id, $name, $checks, $operation, $entity, $events);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -561,6 +561,8 @@ class Manager implements IManager {
|
||||||
|
|
||||||
$operation['checks'][] = $check;
|
$operation['checks'][] = $check;
|
||||||
}
|
}
|
||||||
|
$operation['events'] = json_decode($operation['events'], true);
|
||||||
|
|
||||||
|
|
||||||
return $operation;
|
return $operation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,9 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\WorkflowEngine\Service;
|
namespace OCA\WorkflowEngine\Service;
|
||||||
|
|
||||||
use OCA\WorkflowEngine\AppInfo\Application;
|
|
||||||
use OCA\WorkflowEngine\Entity\File;
|
|
||||||
use OCA\WorkflowEngine\Helper\ScopeContext;
|
use OCA\WorkflowEngine\Helper\ScopeContext;
|
||||||
use OCA\WorkflowEngine\Manager;
|
use OCA\WorkflowEngine\Manager;
|
||||||
use OCP\AppFramework\QueryException;
|
use OCP\AppFramework\QueryException;
|
||||||
use OCP\Files\Node;
|
|
||||||
use OCP\Files\Storage\IStorage;
|
use OCP\Files\Storage\IStorage;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
use OCP\IServerContainer;
|
use OCP\IServerContainer;
|
||||||
|
@ -128,7 +125,7 @@ class RuleMatcher implements IRuleMatcher {
|
||||||
list($entity, $subject) = $entityInfo;
|
list($entity, $subject) = $entityInfo;
|
||||||
$checkInstance->setEntitySubject($entity, $subject);
|
$checkInstance->setEntitySubject($entity, $subject);
|
||||||
}
|
}
|
||||||
} else {
|
} else if(!$checkInstance instanceof ICheck) {
|
||||||
// Check is invalid
|
// Check is invalid
|
||||||
throw new \UnexpectedValueException($this->l->t('Check %s is invalid or does not exist', $check['class']));
|
throw new \UnexpectedValueException($this->l->t('Check %s is invalid or does not exist', $check['class']));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<Multiselect v-model="currentOperator"
|
<Multiselect v-model="currentOperator"
|
||||||
:disabled="!currentOption"
|
:disabled="!currentOption"
|
||||||
:options="operators"
|
:options="operators"
|
||||||
|
class="comparator"
|
||||||
label="name"
|
label="name"
|
||||||
track-by="operator"
|
track-by="operator"
|
||||||
:allow-empty="false"
|
:allow-empty="false"
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
v-model="check.value"
|
v-model="check.value"
|
||||||
:disabled="!currentOption"
|
:disabled="!currentOption"
|
||||||
:check="check"
|
:check="check"
|
||||||
|
class="option"
|
||||||
@input="updateCheck"
|
@input="updateCheck"
|
||||||
@valid="(valid=true) && validate()"
|
@valid="(valid=true) && validate()"
|
||||||
@invalid="(valid=false) && validate()" />
|
@invalid="(valid=false) && validate()" />
|
||||||
|
@ -30,9 +32,10 @@
|
||||||
:class="{ invalid: !valid }"
|
:class="{ invalid: !valid }"
|
||||||
:disabled="!currentOption"
|
:disabled="!currentOption"
|
||||||
:placeholder="valuePlaceholder"
|
:placeholder="valuePlaceholder"
|
||||||
|
class="option"
|
||||||
@input="updateCheck">
|
@input="updateCheck">
|
||||||
<Actions v-if="deleteVisible || !currentOption">
|
<Actions v-if="deleteVisible || !currentOption">
|
||||||
<ActionButton icon="icon-delete" @click="$emit('remove')" />
|
<ActionButton icon="icon-close" @click="$emit('remove')" />
|
||||||
</Actions>
|
</Actions>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -73,17 +76,16 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
Checks() {
|
checks() {
|
||||||
return this.$store.getters.getChecksForEntity(this.rule.entity)
|
return this.$store.getters.getChecksForEntity(this.rule.entity)
|
||||||
},
|
},
|
||||||
operators() {
|
operators() {
|
||||||
if (!this.currentOption) { return [] }
|
if (!this.currentOption) { return [] }
|
||||||
return this.Checks[this.currentOption.class].operators
|
return this.checks[this.currentOption.class].operators
|
||||||
},
|
},
|
||||||
currentComponent() {
|
currentComponent() {
|
||||||
if (!this.currentOption) { return [] }
|
if (!this.currentOption) { return [] }
|
||||||
const currentComponent = this.Checks[this.currentOption.class].component
|
return this.checks[this.currentOption.class].component
|
||||||
return currentComponent
|
|
||||||
},
|
},
|
||||||
valuePlaceholder() {
|
valuePlaceholder() {
|
||||||
if (this.currentOption && this.currentOption.placeholder) {
|
if (this.currentOption && this.currentOption.placeholder) {
|
||||||
|
@ -98,8 +100,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.options = Object.values(this.Checks)
|
this.options = Object.values(this.checks)
|
||||||
this.currentOption = this.Checks[this.check.class]
|
this.currentOption = this.checks[this.check.class]
|
||||||
this.currentOperator = this.operators.find((operator) => operator.operator === this.check.operator)
|
this.currentOperator = this.operators.find((operator) => operator.operator === this.check.operator)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -111,13 +113,8 @@ export default {
|
||||||
},
|
},
|
||||||
validate() {
|
validate() {
|
||||||
if (this.currentOption && this.currentOption.validate) {
|
if (this.currentOption && this.currentOption.validate) {
|
||||||
if (this.currentOption.validate(this.check)) {
|
this.valid = !!this.currentOption.validate(this.check)
|
||||||
this.valid = true
|
|
||||||
} else {
|
|
||||||
this.valid = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.$store.dispatch('setValid', { rule: this.rule, valid: this.rule.valid && this.valid })
|
|
||||||
return this.valid
|
return this.valid
|
||||||
},
|
},
|
||||||
updateCheck() {
|
updateCheck() {
|
||||||
|
@ -128,7 +125,7 @@ export default {
|
||||||
this.check.operator = this.currentOperator.operator
|
this.check.operator = this.currentOperator.operator
|
||||||
|
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
return
|
this.check.invalid = !this.valid
|
||||||
}
|
}
|
||||||
this.$emit('update', this.check)
|
this.$emit('update', this.check)
|
||||||
}
|
}
|
||||||
|
@ -142,14 +139,30 @@ export default {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
& > *:not(.icon-delete) {
|
& > *:not(.close) {
|
||||||
width: 180px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
|
& > .comparator {
|
||||||
|
min-width: 130px;
|
||||||
|
width: 130px;
|
||||||
|
}
|
||||||
|
& > .option {
|
||||||
|
min-width: 230px;
|
||||||
|
width: 230px;
|
||||||
|
}
|
||||||
& > .multiselect,
|
& > .multiselect,
|
||||||
& > input[type=text] {
|
& > input[type=text] {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.multiselect::v-deep .multiselect__content-wrapper li>span,
|
||||||
|
.multiselect::v-deep .multiselect__single {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
input[type=text] {
|
input[type=text] {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -157,14 +170,12 @@ export default {
|
||||||
::placeholder {
|
::placeholder {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
.icon-delete {
|
button.action-item.action-item--single.icon-close {
|
||||||
|
height: 44px;
|
||||||
|
width: 44px;
|
||||||
margin-top: -5px;
|
margin-top: -5px;
|
||||||
margin-bottom: -5px;
|
margin-bottom: -5px;
|
||||||
}
|
}
|
||||||
button.action-item.action-item--single.icon-delete {
|
|
||||||
height: 34px;
|
|
||||||
width: 34px;
|
|
||||||
}
|
|
||||||
.invalid {
|
.invalid {
|
||||||
border: 1px solid var(--color-error) !important;
|
border: 1px solid var(--color-error) !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,20 @@
|
||||||
:tagging="false"
|
:tagging="false"
|
||||||
@input="setValue">
|
@input="setValue">
|
||||||
<template slot="singleLabel" slot-scope="props">
|
<template slot="singleLabel" slot-scope="props">
|
||||||
<span class="option__icon" :class="props.option.icon" />
|
<span v-if="props.option.icon" class="option__icon" :class="props.option.icon" />
|
||||||
|
<img v-else :src="props.option.iconUrl">
|
||||||
<span class="option__title option__title_single">{{ props.option.label }}</span>
|
<span class="option__title option__title_single">{{ props.option.label }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template slot="option" slot-scope="props">
|
<template slot="option" slot-scope="props">
|
||||||
<span class="option__icon" :class="props.option.icon" />
|
<span v-if="props.option.icon" class="option__icon" :class="props.option.icon" />
|
||||||
|
<img v-else :src="props.option.iconUrl">
|
||||||
<span class="option__title">{{ props.option.label }}</span>
|
<span class="option__title">{{ props.option.label }}</span>
|
||||||
</template>
|
</template>
|
||||||
</Multiselect>
|
</Multiselect>
|
||||||
<input v-if="!isPredefined"
|
<input v-if="!isPredefined"
|
||||||
type="text"
|
type="text"
|
||||||
:value="currentValue.pattern"
|
:value="currentValue.pattern"
|
||||||
|
:placeholder="t('workflowengine', 'e.g. httpd/unix-directory')"
|
||||||
@input="updateCustom">
|
@input="updateCustom">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -68,12 +71,12 @@ export default {
|
||||||
pattern: '/image\\/.*/'
|
pattern: '/image\\/.*/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'icon-category-office',
|
iconUrl: OC.imagePath('core', 'filetypes/x-office-document'),
|
||||||
label: t('workflowengine', 'Office documents'),
|
label: t('workflowengine', 'Office documents'),
|
||||||
pattern: '/(vnd\\.(ms-|openxmlformats-).*))$/'
|
pattern: '/(vnd\\.(ms-|openxmlformats-).*))$/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'icon-filetype-file',
|
iconUrl: OC.imagePath('core', 'filetypes/application-pdf'),
|
||||||
label: t('workflowengine', 'PDF documents'),
|
label: t('workflowengine', 'PDF documents'),
|
||||||
pattern: 'application/pdf'
|
pattern: 'application/pdf'
|
||||||
}
|
}
|
||||||
|
@ -130,3 +133,15 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.multiselect, input[type='text'] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.multiselect >>> .multiselect__content-wrapper li>span,
|
||||||
|
.multiselect >>> .multiselect__single {
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<template>
|
<template>
|
||||||
<MultiselectTag v-model="newValue"
|
<MultiselectTag v-model="newValue"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
label="Select a tag"
|
:label="t('workflowengine', 'Select a tag')"
|
||||||
@input="update" />
|
@input="update" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -56,10 +56,8 @@ export default {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Array,
|
type: [String, Array],
|
||||||
default() {
|
default: null
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -67,7 +65,7 @@ export default {
|
||||||
},
|
},
|
||||||
multiple: {
|
multiple: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="timeslot">
|
<div class="timeslot">
|
||||||
<Multiselect v-model="newValue.timezone" :options="timezones" @input="update" />
|
|
||||||
<input v-model="newValue.startTime"
|
<input v-model="newValue.startTime"
|
||||||
type="text"
|
type="text"
|
||||||
class="timeslot--start"
|
class="timeslot--start"
|
||||||
placeholder="08:00"
|
placeholder="e.g. 08:00"
|
||||||
@input="update">
|
@input="update">
|
||||||
<input v-model="newValue.endTime"
|
<input v-model="newValue.endTime"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="18:00"
|
placeholder="e.g. 18:00"
|
||||||
@input="update">
|
@input="update">
|
||||||
|
<p v-if="!valid" class="invalid-hint">
|
||||||
|
{{ t('workflowengine', 'Please enter a valid time span') }}
|
||||||
|
</p>
|
||||||
|
<Multiselect v-show="valid"
|
||||||
|
v-model="newValue.timezone"
|
||||||
|
:options="timezones"
|
||||||
|
@input="update" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -30,7 +36,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '1 MB'
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -46,14 +52,17 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateInternalValue(value) {
|
updateInternalValue(value) {
|
||||||
var data = JSON.parse(value)
|
try {
|
||||||
var startTime = data[0].split(' ', 2)[0]
|
const data = JSON.parse(value)
|
||||||
var endTime = data[1].split(' ', 2)[0]
|
if (data.length === 2) {
|
||||||
var timezone = data[0].split(' ', 2)[1]
|
this.newValue = {
|
||||||
this.newValue = {
|
startTime: data[0].split(' ', 2)[0],
|
||||||
startTime: startTime,
|
endTime: data[1].split(' ', 2)[0],
|
||||||
endTime: endTime,
|
timezone: data[0].split(' ', 2)[1]
|
||||||
timezone: timezone
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// ignore invalid values
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validate() {
|
validate() {
|
||||||
|
@ -86,14 +95,23 @@ export default {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.multiselect::v-deep .multiselect__tags:not(:hover):not(:focus):not(:active) {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=text] {
|
input[type=text] {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
|
||||||
&.timeslot--start {
|
&.timeslot--start {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
width: calc(50% - 5px);
|
width: calc(50% - 5px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invalid-hint {
|
||||||
|
color: var(--color-text-maxcontrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -137,3 +137,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.multiselect, input[type='text'] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -27,19 +27,22 @@
|
||||||
:placeholder="t('workflowengine', 'Select a user agent')"
|
:placeholder="t('workflowengine', 'Select a user agent')"
|
||||||
label="label"
|
label="label"
|
||||||
track-by="pattern"
|
track-by="pattern"
|
||||||
group-values="children"
|
|
||||||
group-label="label"
|
|
||||||
:options="options"
|
:options="options"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:tagging="false"
|
:tagging="false"
|
||||||
@input="setValue">
|
@input="setValue">
|
||||||
<template slot="singleLabel" slot-scope="props">
|
<template slot="singleLabel" slot-scope="props">
|
||||||
<span class="option__icon" :class="props.option.icon" />
|
<span class="option__icon" :class="props.option.icon" />
|
||||||
<span class="option__title option__title_single">{{ props.option.label }}</span>
|
<!-- v-html can be used here as t() always passes our translated strings though DOMPurify.sanitize -->
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<span class="option__title option__title_single" v-html="props.option.label" />
|
||||||
</template>
|
</template>
|
||||||
<template slot="option" slot-scope="props">
|
<template slot="option" slot-scope="props">
|
||||||
<span class="option__icon" :class="props.option.icon" />
|
<span class="option__icon" :class="props.option.icon" />
|
||||||
<span class="option__title">{{ props.option.label }} {{ props.option.$groupLabel }}</span>
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<span v-if="props.option.$groupLabel" class="option__title" v-html="props.option.$groupLabel" />
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<span v-else class="option__title" v-html="props.option.label" />
|
||||||
</template>
|
</template>
|
||||||
</Multiselect>
|
</Multiselect>
|
||||||
<input v-if="!isPredefined"
|
<input v-if="!isPredefined"
|
||||||
|
@ -65,15 +68,10 @@ export default {
|
||||||
return {
|
return {
|
||||||
newValue: '',
|
newValue: '',
|
||||||
predefinedTypes: [
|
predefinedTypes: [
|
||||||
{
|
{ pattern: 'android', label: t('workflowengine', 'Android client'), icon: 'icon-phone' },
|
||||||
label: t('workflowengine', 'Sync clients'),
|
{ pattern: 'ios', label: t('workflowengine', 'iOS client'), icon: 'icon-phone' },
|
||||||
children: [
|
{ pattern: 'desktop', label: t('workflowengine', 'Desktop client'), icon: 'icon-desktop' },
|
||||||
{ pattern: 'android', label: t('workflowengine', 'Android client'), icon: 'icon-phone' },
|
{ pattern: 'mail', label: t('workflowengine', 'Thunderbird & Outlook addons'), icon: 'icon-mail' }
|
||||||
{ 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' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -83,8 +81,6 @@ export default {
|
||||||
},
|
},
|
||||||
matchingPredefined() {
|
matchingPredefined() {
|
||||||
return this.predefinedTypes
|
return this.predefinedTypes
|
||||||
.map(groups => groups.children)
|
|
||||||
.flat()
|
|
||||||
.find((type) => this.newValue === type.pattern)
|
.find((type) => this.newValue === type.pattern)
|
||||||
},
|
},
|
||||||
isPredefined() {
|
isPredefined() {
|
||||||
|
@ -92,14 +88,9 @@ export default {
|
||||||
},
|
},
|
||||||
customValue() {
|
customValue() {
|
||||||
return {
|
return {
|
||||||
label: t('workflowengine', 'Others'),
|
icon: 'icon-settings-dark',
|
||||||
children: [
|
label: t('workflowengine', 'Custom user agent'),
|
||||||
{
|
pattern: ''
|
||||||
icon: 'icon-settings-dark',
|
|
||||||
label: t('workflowengine', 'Custom user agent'),
|
|
||||||
pattern: ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
currentValue() {
|
currentValue() {
|
||||||
|
@ -115,8 +106,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
validateRegex(string) {
|
validateRegex(string) {
|
||||||
var regexRegex = /^\/(.*)\/([gui]{0,3})$/
|
const regexRegex = /^\/(.*)\/([gui]{0,3})$/
|
||||||
var result = regexRegex.exec(string)
|
const result = regexRegex.exec(string)
|
||||||
return result !== null
|
return result !== null
|
||||||
},
|
},
|
||||||
setValue(value) {
|
setValue(value) {
|
||||||
|
@ -133,3 +124,32 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.multiselect, input[type='text'] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect .multiselect__content-wrapper li>span {
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.multiselect::v-deep .multiselect__single {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.option__icon {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 30px;
|
||||||
|
background-position: left;
|
||||||
|
}
|
||||||
|
.option__title {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -22,56 +22,91 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Multiselect v-model="newValue"
|
<Multiselect :value="currentValue"
|
||||||
:class="{'icon-loading-small': groups.length === 0}"
|
:loading="status.isLoading && groups.length === 0"
|
||||||
:options="groups"
|
:options="groups"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
label="displayname"
|
label="displayname"
|
||||||
track-by="id"
|
track-by="id"
|
||||||
@input="setValue" />
|
@search-change="searchAsync"
|
||||||
|
@input="(value) => $emit('input', value.id)" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect'
|
import { Multiselect } from 'nextcloud-vue/dist/Components/Multiselect'
|
||||||
import valueMixin from '../../mixins/valueMixin'
|
|
||||||
import axios from '@nextcloud/axios'
|
import axios from '@nextcloud/axios'
|
||||||
|
|
||||||
|
const groups = []
|
||||||
|
const status = {
|
||||||
|
isLoading: false
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RequestUserGroup',
|
name: 'RequestUserGroup',
|
||||||
components: {
|
components: {
|
||||||
Multiselect
|
Multiselect
|
||||||
},
|
},
|
||||||
mixins: [
|
props: {
|
||||||
valueMixin
|
value: {
|
||||||
],
|
type: String,
|
||||||
data() {
|
default: ''
|
||||||
return {
|
},
|
||||||
groups: []
|
check: {
|
||||||
|
type: Object,
|
||||||
|
default: () => { return {} }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
data() {
|
||||||
axios.get(OC.linkToOCS('cloud', 2) + 'groups').then((response) => {
|
return {
|
||||||
this.groups = response.data.ocs.data.groups.reduce((obj, item) => {
|
groups: groups,
|
||||||
obj.push({
|
status: status
|
||||||
id: item,
|
}
|
||||||
displayname: item
|
},
|
||||||
})
|
computed: {
|
||||||
return obj
|
currentValue() {
|
||||||
}, [])
|
return this.groups.find(group => group.id === this.value) || null
|
||||||
this.updateInternalValue(this.value)
|
}
|
||||||
}, (error) => {
|
},
|
||||||
console.error('Error while loading group list', error.response)
|
async mounted() {
|
||||||
})
|
if (this.groups.length === 0) {
|
||||||
|
await this.searchAsync('')
|
||||||
|
}
|
||||||
|
if (this.currentValue === null) {
|
||||||
|
await this.searchAsync(this.value)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateInternalValue() {
|
searchAsync(searchQuery) {
|
||||||
this.newValue = this.groups.find(group => group.id === this.value) || null
|
if (this.status.isLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.status.isLoading = true
|
||||||
|
return axios.get(OC.linkToOCS('cloud', 2) + 'groups?limit=20&search=' + encodeURI(searchQuery)).then((response) => {
|
||||||
|
response.data.ocs.data.groups.reduce((obj, item) => {
|
||||||
|
obj.push({
|
||||||
|
id: item,
|
||||||
|
displayname: item
|
||||||
|
})
|
||||||
|
return obj
|
||||||
|
}, []).forEach((group) => this.addGroup(group))
|
||||||
|
this.status.isLoading = false
|
||||||
|
}, (error) => {
|
||||||
|
console.error('Error while loading group list', error.response)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
setValue(value) {
|
addGroup(group) {
|
||||||
if (value !== null) {
|
const index = this.groups.findIndex((item) => item.id === group.id)
|
||||||
this.$emit('input', this.newValue.id)
|
if (index === -1) {
|
||||||
|
this.groups.push(group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.multiselect {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -65,7 +65,7 @@ const FileChecks = [
|
||||||
{ operator: 'greater', name: t('workflowengine', 'greater') }
|
{ operator: 'greater', name: t('workflowengine', 'greater') }
|
||||||
],
|
],
|
||||||
placeholder: (check) => '5 MB',
|
placeholder: (check) => '5 MB',
|
||||||
validate: (check) => check.value.match(/^[0-9]+[ ]?[kmgt]?b$/i) !== null
|
validate: (check) => check.value ? check.value.match(/^[0-9]+[ ]?[kmgt]?b$/i) !== null : false
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="event">
|
||||||
<div v-if="operation.isComplex && operation.fixedEntity !== ''" class="isComplex">
|
<div v-if="operation.isComplex && operation.fixedEntity !== ''" class="isComplex">
|
||||||
<img class="option__icon" :src="entity.icon">
|
<img class="option__icon" :src="entity.icon">
|
||||||
<span class="option__title option__title_single">{{ operation.triggerHint }}</span>
|
<span class="option__title option__title_single">{{ operation.triggerHint }}</span>
|
||||||
|
@ -7,14 +7,16 @@
|
||||||
<Multiselect v-else
|
<Multiselect v-else
|
||||||
:value="currentEvent"
|
:value="currentEvent"
|
||||||
:options="allEvents"
|
:options="allEvents"
|
||||||
label="eventName"
|
|
||||||
track-by="id"
|
track-by="id"
|
||||||
:allow-empty="false"
|
:multiple="true"
|
||||||
|
:auto-limit="false"
|
||||||
:disabled="allEvents.length <= 1"
|
:disabled="allEvents.length <= 1"
|
||||||
@input="updateEvent">
|
@input="updateEvent">
|
||||||
<template slot="singleLabel" slot-scope="props">
|
<template slot="selection" slot-scope="{ values, search, isOpen }">
|
||||||
<img class="option__icon" :src="props.option.entity.icon">
|
<div v-if="values.length && !isOpen" class="eventlist">
|
||||||
<span class="option__title option__title_single">{{ props.option.displayName }}</span>
|
<img class="option__icon" :src="values[0].entity.icon">
|
||||||
|
<span v-for="(value, index) in values" :key="value.id" class="text option__title option__title_single">{{ value.displayName }} <span v-if="index+1 < values.length">, </span></span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template slot="option" slot-scope="props">
|
<template slot="option" slot-scope="props">
|
||||||
<img class="option__icon" :src="props.option.entity.icon">
|
<img class="option__icon" :src="props.option.entity.icon">
|
||||||
|
@ -49,23 +51,22 @@ export default {
|
||||||
return this.$store.getters.getEventsForOperation(this.operation)
|
return this.$store.getters.getEventsForOperation(this.operation)
|
||||||
},
|
},
|
||||||
currentEvent() {
|
currentEvent() {
|
||||||
if (!this.rule.events) {
|
return this.allEvents.filter(event => event.entity.id === this.rule.entity && this.rule.events.indexOf(event.eventName) !== -1)
|
||||||
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: {
|
methods: {
|
||||||
updateEvent(event) {
|
updateEvent(events) {
|
||||||
this.$set(this.rule, 'entity', event.entity.id)
|
this.$set(this.rule, 'events', events.map(event => event.eventName))
|
||||||
this.$set(this.rule, 'events', [event.eventName])
|
this.$emit('update', this.rule)
|
||||||
this.$store.dispatch('updateRule', this.rule)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.event {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
.isComplex {
|
.isComplex {
|
||||||
img {
|
img {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@ -78,6 +79,11 @@ export default {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.multiselect {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 550px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
.multiselect::v-deep .multiselect__single {
|
.multiselect::v-deep .multiselect__single {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
@ -86,8 +92,10 @@ export default {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect::v-deep .multiselect__tags .multiselect__single {
|
.multiselect::v-deep .multiselect__tags {
|
||||||
background-color: var(--color-main-background) !important;
|
background-color: var(--color-main-background) !important;
|
||||||
|
height: auto;
|
||||||
|
min-height: 34px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect:not(.multiselect--disabled)::v-deep .multiselect__tags .multiselect__single {
|
.multiselect:not(.multiselect--disabled)::v-deep .multiselect__tags .multiselect__single {
|
||||||
|
@ -107,4 +115,9 @@ export default {
|
||||||
.option__title_single {
|
.option__title_single {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.eventlist img,
|
||||||
|
.eventlist .text {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -55,6 +55,7 @@ export default {
|
||||||
.actions__item_options {
|
.actions__item_options {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
padding-left: 60px;
|
||||||
}
|
}
|
||||||
h3, small {
|
h3, small {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
@ -63,7 +64,7 @@ export default {
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
small {
|
small {
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
|
@ -82,6 +83,7 @@ export default {
|
||||||
.actions__item__description {
|
.actions__item__description {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
width: calc(100% - 105px);
|
||||||
small {
|
small {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="section rule" :style="{ borderLeftColor: operation.color || '' }">
|
<div v-if="operation" class="section rule" :style="{ borderLeftColor: operation.color || '' }">
|
||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
<p>
|
<p>
|
||||||
<span>{{ t('workflowengine', 'When') }}</span>
|
<span>{{ t('workflowengine', 'When') }}</span>
|
||||||
|
@ -23,28 +23,26 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flow-icon icon-confirm" />
|
<div class="flow-icon icon-confirm" />
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<div class="buttons">
|
|
||||||
<Actions>
|
|
||||||
<ActionButton v-if="rule.id < -1" icon="icon-close" @click="cancelRule">
|
|
||||||
{{ t('workflowengine', 'Cancel rule creation') }}
|
|
||||||
</ActionButton>
|
|
||||||
<ActionButton v-else icon="icon-close" @click="deleteRule">
|
|
||||||
{{ t('workflowengine', 'Remove rule') }}
|
|
||||||
</ActionButton>
|
|
||||||
</Actions>
|
|
||||||
</div>
|
|
||||||
<Operation :operation="operation" :colored="false">
|
<Operation :operation="operation" :colored="false">
|
||||||
<component :is="operation.options"
|
<component :is="operation.options"
|
||||||
v-if="operation.options"
|
v-if="operation.options"
|
||||||
v-model="rule.operation"
|
v-model="rule.operation"
|
||||||
@input="updateOperation" />
|
@input="updateOperation" />
|
||||||
</Operation>
|
</Operation>
|
||||||
<button v-tooltip="ruleStatus.tooltip"
|
<div class="buttons">
|
||||||
class="status-button icon"
|
<button v-tooltip="ruleStatus.tooltip"
|
||||||
:class="ruleStatus.class"
|
class="status-button icon"
|
||||||
@click="saveRule">
|
:class="ruleStatus.class"
|
||||||
{{ ruleStatus.title }}
|
@click="saveRule">
|
||||||
</button>
|
{{ ruleStatus.title }}
|
||||||
|
</button>
|
||||||
|
<button v-if="rule.id < -1" @click="cancelRule">
|
||||||
|
{{ t('workflowengine', 'Cancel') }}
|
||||||
|
</button>
|
||||||
|
<button v-else @click="deleteRule">
|
||||||
|
{{ t('workflowengine', 'Delete') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -85,7 +83,7 @@ export default {
|
||||||
return this.$store.getters.getOperationForRule(this.rule)
|
return this.$store.getters.getOperationForRule(this.rule)
|
||||||
},
|
},
|
||||||
ruleStatus() {
|
ruleStatus() {
|
||||||
if (this.error || !this.rule.valid) {
|
if (this.error || !this.rule.valid || this.rule.checks.some((check) => check.invalid === true)) {
|
||||||
return {
|
return {
|
||||||
title: t('workflowengine', 'The configuration is invalid'),
|
title: t('workflowengine', 'The configuration is invalid'),
|
||||||
class: 'icon-close-white invalid',
|
class: 'icon-close-white invalid',
|
||||||
|
@ -163,11 +161,18 @@ export default {
|
||||||
background-position: 10px center;
|
background-position: 10px center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: block;
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.status-button {
|
.status-button {
|
||||||
transition: 0.5s ease all;
|
transition: 0.5s ease all;
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: 3px 10px 3px auto;
|
||||||
margin-right: 0;
|
|
||||||
}
|
}
|
||||||
.status-button.primary {
|
.status-button.primary {
|
||||||
padding-left: 32px;
|
padding-left: 32px;
|
||||||
|
@ -199,12 +204,6 @@ export default {
|
||||||
.action {
|
.action {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
position: relative;
|
position: relative;
|
||||||
.buttons {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
display: flex;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.icon-confirm {
|
.icon-confirm {
|
||||||
background-position: right 27px;
|
background-position: right 27px;
|
||||||
|
@ -238,6 +237,7 @@ export default {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 180px;
|
width: 180px;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
|
color: var(--color-text-maxcontrast);
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
|
|
@ -22,8 +22,9 @@
|
||||||
|
|
||||||
import { loadState } from '@nextcloud/initial-state'
|
import { loadState } from '@nextcloud/initial-state'
|
||||||
|
|
||||||
|
const scopeValue = loadState('workflowengine', 'scope') === 0 ? 'global' : 'user'
|
||||||
|
|
||||||
const getApiUrl = (url) => {
|
const getApiUrl = (url) => {
|
||||||
const scopeValue = loadState('workflowengine', 'scope') === 0 ? 'global' : 'user'
|
|
||||||
return OC.linkToOCS('apps/workflowengine/api/v1/workflows', 2) + scopeValue + url + '?format=json'
|
return OC.linkToOCS('apps/workflowengine/api/v1/workflows', 2) + scopeValue + url + '?format=json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,23 +19,29 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
const regexRegex = /^\/(.*)\/([gui]{0,3})$/
|
||||||
|
const regexIPv4 = /^(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])$/
|
||||||
|
const regexIPv6 = /^(([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])$/
|
||||||
|
|
||||||
const validateRegex = function(string) {
|
const validateRegex = function(string) {
|
||||||
var regexRegex = /^\/(.*)\/([gui]{0,3})$/
|
if (!string) {
|
||||||
var result = regexRegex.exec(string)
|
return false
|
||||||
return result !== null
|
}
|
||||||
|
return regexRegex.exec(string) !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
const validateIPv4 = function(string) {
|
const 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])$/
|
if (!string) {
|
||||||
var result = regexRegex.exec(string)
|
return false
|
||||||
return result !== null
|
}
|
||||||
|
return regexIPv4.exec(string) !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
const validateIPv6 = function(string) {
|
const 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])$/
|
if (!string) {
|
||||||
var result = regexRegex.exec(string)
|
return false
|
||||||
return result !== null
|
}
|
||||||
|
return regexIPv6.exec(string) !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
const stringValidator = (check) => {
|
const stringValidator = (check) => {
|
||||||
|
|
|
@ -71,7 +71,9 @@ const store = new Vuex.Store({
|
||||||
plugin = Object.assign(
|
plugin = Object.assign(
|
||||||
{ color: 'var(--color-primary-element)' },
|
{ color: 'var(--color-primary-element)' },
|
||||||
plugin, state.operations[plugin.id] || {})
|
plugin, state.operations[plugin.id] || {})
|
||||||
Vue.set(state.operations, plugin.id, plugin)
|
if (typeof state.operations[plugin.id] !== 'undefined') {
|
||||||
|
Vue.set(state.operations, plugin.id, plugin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
use OCA\WorkflowEngine\AppInfo\Application;
|
use OCA\WorkflowEngine\AppInfo\Application;
|
||||||
style(Application::APP_ID, 'multiselect');
|
|
||||||
|
|
||||||
/** @var array $_ */
|
/** @var array $_ */
|
||||||
/** @var \OCP\IL10N $l */
|
/** @var \OCP\IL10N $l */
|
||||||
|
|
|
@ -24,9 +24,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCP\WorkflowEngine;
|
namespace OCP\WorkflowEngine;
|
||||||
|
|
||||||
|
|
||||||
use OCP\Files\Storage\IStorage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface IFileCheck
|
* Interface IFileCheck
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue