mirror of https://github.com/rancher/dashboard.git
221 lines
5.7 KiB
Vue
221 lines
5.7 KiB
Vue
<script>
|
|
import pullAt from 'lodash/pullAt';
|
|
import pickBy from 'lodash/pickBy';
|
|
import { isEmpty } from 'lodash';
|
|
import findIndex from 'lodash/findIndex';
|
|
import { typeOf } from '@/utils/sort';
|
|
import KeyValue from '@/components/form/KeyValue';
|
|
import StringMatch from '@/edit/rio.cattle.io.router/StringMatch';
|
|
import LabeledInput from '@/components/form/LabeledInput';
|
|
import createEditView from '../../mixins/create-edit-view';
|
|
export default {
|
|
components: {
|
|
StringMatch, KeyValue, LabeledInput
|
|
},
|
|
mixins: [createEditView],
|
|
props: {
|
|
spec: {
|
|
type: Object,
|
|
default: () => {
|
|
return {};
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
const {
|
|
headers = [], methods = [], path = {}, cookies = []
|
|
} = this.spec;
|
|
|
|
let hostHeader;
|
|
|
|
if (headers.length) {
|
|
hostHeader = pullAt(headers, findIndex(headers, header => header.name === 'host' && Object.keys(header.value)[0] === 'exact'))[0];
|
|
}
|
|
if (!hostHeader) {
|
|
hostHeader = { name: 'host', value: { exact: '' } };
|
|
}
|
|
|
|
return {
|
|
httpMethods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'],
|
|
headers,
|
|
methods,
|
|
cookies,
|
|
path,
|
|
host: hostHeader
|
|
};
|
|
},
|
|
computed: {
|
|
formatted() {
|
|
const all = {
|
|
headers: !!this.host.value.exact ? [this.hostHeader, ...this.headers] : this.headers,
|
|
methods: this.methods,
|
|
path: this.path,
|
|
cookies: this.cookies
|
|
};
|
|
|
|
const out = pickBy(all, (value, key) => {
|
|
if (typeOf(value) === 'array') {
|
|
value.forEach((condition) => {
|
|
if (typeOf(condition) === 'string') {
|
|
return true;
|
|
} else {
|
|
return !isEmpty(condition);
|
|
}
|
|
});
|
|
|
|
return value.length;
|
|
} else {
|
|
return !!Object.values(value)[0];
|
|
}
|
|
});
|
|
|
|
return out;
|
|
},
|
|
},
|
|
methods: {
|
|
matchChange() {
|
|
this.$emit('input', this.formatted);
|
|
},
|
|
isSelected(opt) {
|
|
return this.methods.includes(opt);
|
|
},
|
|
change(type, val) {
|
|
this.$set(this, type, val);
|
|
},
|
|
changeKV(type, val) {
|
|
const set = [];
|
|
|
|
for (const key in val) {
|
|
const name = key;
|
|
const value = val[name];
|
|
|
|
set.push({ name, value });
|
|
}
|
|
|
|
this[type] = set;
|
|
},
|
|
changePath(stringmatch) {
|
|
const pathString = Object.values(stringmatch)[0];
|
|
const method = Object.keys(stringmatch)[0];
|
|
|
|
if (pathString.charAt(0) !== '/') {
|
|
this.$set(this.path, method, `/${ pathString }`);
|
|
} else {
|
|
this.path[method] = pathString;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="match" @change="matchChange" @input="matchChange">
|
|
<div class="row inputs">
|
|
<v-select
|
|
class="col span-4"
|
|
multiple
|
|
:close-on-select="false"
|
|
:options="httpMethods.filter(opt=>!isSelected(opt))"
|
|
:value="methods"
|
|
placeholder="Method"
|
|
:disabled="isView"
|
|
@input="e=>{change('methods', e); matchChange()}"
|
|
>
|
|
</v-select>
|
|
<div class="col span-4">
|
|
<LabeledInput v-if="host" v-model="host.value.exact" label="Host header" />
|
|
</div>
|
|
<div class="col span-4">
|
|
<StringMatch :spec="path" label="Path" @input="e=>changePath(e)" />
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col span-6">
|
|
<h5>Headers</h5>
|
|
<KeyValue
|
|
:value="headers"
|
|
key-name="name"
|
|
:as-map="false"
|
|
add-label="Add Header Rule"
|
|
:protip="false"
|
|
:pad-left="false"
|
|
:read-allowed="false"
|
|
@input="e=>changeKV('headers', e)"
|
|
>
|
|
<template v-slot:removeButton="buttonProps">
|
|
<button :disabled="!isView" type="button" class="btn btn-sm role-link" @click="buttonProps.remove(buttonProps.idx)">
|
|
REMOVE
|
|
</button>
|
|
</template>
|
|
<template v-slot:value="valProps">
|
|
<StringMatch
|
|
:spec="valProps.row.value"
|
|
:options="['exact', 'prefix', 'regexp']"
|
|
placeholder="e.g. bar"
|
|
@input="e=>{
|
|
valProps.row.value = e
|
|
valProps.queueUpdate()
|
|
}"
|
|
/>
|
|
</template>
|
|
</KeyValue>
|
|
</div>
|
|
<div class="col span-6">
|
|
<h5>Cookies</h5>
|
|
<KeyValue
|
|
key-name="name"
|
|
:value="cookies"
|
|
:as-map="false"
|
|
add-label="Add Cookie Rule"
|
|
:protip="false"
|
|
:pad-left="false"
|
|
:read-allowed="false"
|
|
@input="e=>changeKV('cookies', e)"
|
|
>
|
|
<template v-slot:removeButton="buttonProps">
|
|
<button :disabled="!isView" type="button" class="btn btn-sm role-link" @click="buttonProps.remove(buttonProps.idx)">
|
|
REMOVE
|
|
</button>
|
|
</template>
|
|
<template v-slot:value="valProps">
|
|
<StringMatch
|
|
:spec="valProps.row.value"
|
|
:options="['exact', 'prefix']"
|
|
placeholder="e.g. bar"
|
|
@input="e=>{
|
|
valProps.row.value = e
|
|
valProps.queueUpdate()
|
|
}"
|
|
/>
|
|
</template>
|
|
</KeyValue>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang='scss'>
|
|
.match {
|
|
& .fixed tr {
|
|
& .key, .value, .remove {
|
|
vertical-align: middle;
|
|
}
|
|
& .remove {
|
|
text-align:left;
|
|
& button.role-link {
|
|
padding: 0 0 0 0;
|
|
}
|
|
}
|
|
& td {
|
|
margin-right: 5px;
|
|
& .labeled-input {
|
|
padding: 0;
|
|
& label:nth-child(1) {
|
|
bottom: -2px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|