blob: c5b29a17e795029dd978fa62288acf5ada32ea41 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<div class="form-layout">
<div v-if="(resource || payloadUrl)">
<a-divider />
<a-collapse
v-model:activeKey="collapseKey">
<a-collapse-panel
:showArrow="isResponseNotEmpty"
key="1"
:collapsible="(resource || payloadUrl) ? 'enabled' : 'disabled'">
<template #header>
<a-row style="width: 100%;">
<a-col :span="22">
<tooltip-label :title="$t('label.status')" v-if="isNotShowStatus"/>
<status class="status" :text="response.success ? 'success' : 'error'" displayText v-else/>
</a-col>
<a-col :span="2">
<div v-if="showActions">
<a-spin :spinning="loading" size="small" v-if="loading" />
<div v-else>
<a-button
type="primary"
size="small"
@click.stop="testWebhookDelivery">
<render-icon icon="reload-outlined" />
<div class="ant-btn__progress-overlay" :style="computedOverlayStyle"></div>
</a-button>
</div>
</div>
</a-col>
</a-row>
</template>
<div v-if="isResponseNotEmpty">
<a-row>
<a-col :span="8">
<div class="response-detail-item" v-if="('success' in response)">
<div class="response-detail-item__label"><strong>{{ $t('label.success') }}</strong></div>
<div class="response-detail-item__details">
<status class="status" :text="response.success ? 'success' : 'error'"/>
</div>
</div>
</a-col>
<a-col :span="8">
<div class="response-detail-item" v-if="response.startdate && response.enddate">
<div class="response-detail-item__label"><strong>{{ $t('label.duration') }}</strong></div>
<div class="response-detail-item__details">
{{ responseDuration }}
</div>
</div>
</a-col>
<a-col :span="8">
<div class="response-detail-item" v-if="response.managementserverid">
<div class="response-detail-item__label"><strong>{{ $t('label.managementserverid') }}</strong></div>
<div class="response-detail-item__details">
{{ response.managementservername }}
</div>
</div>
</a-col>
</a-row>
<a-alert
:type="response.success ? 'success' : 'error'"
:showIcon="true"
:message="$t('label.response')"
:description="response.response ? response.response : 'Empty response'" />
</div>
</a-collapse-panel>
</a-collapse>
<a-divider />
</div>
</div>
</template>
<script>
import { postAPI } from '@/api'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import Status from '@/components/widgets/Status'
export default {
name: 'TestWebhookDeliveryView',
components: {
TooltipLabel,
Status
},
props: {
resource: {
type: Object
},
payload: {
type: String
},
payloadUrl: {
type: String
},
sslVerification: {
type: Boolean,
default: false
},
secretKey: {
type: String
},
showActions: {
type: Boolean,
default: false
}
},
data () {
return {
response: {},
collapseKey: undefined,
loading: false,
testDeliveryInterval: null,
testDeliveryIntervalCouter: 0
}
},
beforeCreate () {
this.timedDeliveryWait = 4000
},
beforeUnmount () {
this.resetTestDeliveryInterval()
},
computed: {
isResponseNotEmpty () {
return this.response && Object.keys(this.response).length > 0
},
isNotShowStatus () {
return !this.isResponseNotEmpty ||
this.collapseKey === '1' ||
(Array.isArray(this.collapseKey) &&
this.collapseKey.length > 0 &&
this.collapseKey[0] === '1')
},
responseDuration () {
if (!this.response.startdate || !this.response.enddate) {
return ''
}
var duration = Date.parse(this.response.enddate) - Date.parse(this.response.startdate)
return (duration > 0 ? duration / 1000.0 : 0) + ''
},
computedOverlayStyle () {
var opacity = this.testDeliveryIntervalCouter <= 10.0 ? 0 : 0.3
var width = this.testDeliveryIntervalCouter
return 'opacity: ' + opacity + '; width: ' + width + '%;'
}
},
methods: {
validateUrl (url) {
const urlPattern = /^(http|https):\/\/[^ "]+$/
urlPattern.test(url)
},
resetTestDeliveryInterval () {
if (this.testDeliveryInterval) {
clearInterval(this.testDeliveryInterval)
}
this.testDeliveryIntervalCouter = 0
},
testWebhookDelivery () {
this.resetTestDeliveryInterval()
this.response = {}
this.loading = true
this.$emit('change-loading', this.loading)
var params = {}
if (this.resource) {
params.webhookid = this.resource.id
}
if (this.payload) {
params.payload = this.payload
}
if (this.payloadUrl) {
params.payloadUrl = this.payloadUrl
}
if (this.sslVerification) {
params.payload = this.sslVerification
}
if (this.secretKey) {
params.secretKey = this.secretKey
}
postAPI('executeWebhookDelivery', params).then(response => {
this.response = response.executewebhookdeliveryresponse.webhookdelivery
this.$emit('update-success', response.success)
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.loading = false
this.$emit('change-loading', this.loading)
})
},
getNormalizedPayloadUrl () {
if (!this.payloadUrl || this.payloadUrl === '' || this.validateUrl(this.payloadUrl)) {
return this.payloadUrl
}
return 'http://' + this.payloadUrl
},
executeTestWebhookDeliveryOrReset () {
const url = this.getNormalizedPayloadUrl()
if (url) {
this.testWebhookDelivery()
return
}
this.resetTestDeliveryInterval()
},
timedTestWebhookDelivery () {
const url = this.getNormalizedPayloadUrl()
this.resetTestDeliveryInterval()
this.testDeliveryInterval = setInterval(() => {
if (!url) {
this.resetTestDeliveryInterval()
return
}
this.testDeliveryIntervalCouter = this.testDeliveryIntervalCouter + 1
if (this.testDeliveryIntervalCouter >= 100) {
this.executeTestWebhookDeliveryOrReset()
}
}, this.timedDeliveryWait / 100)
}
}
}
</script>
<style scoped lang="scss">
.response-detail-item {
margin-bottom: 20px;
word-break: break-all;
&__details {
display: flex;
align-items: center;
&--start {
align-items: flex-start;
i {
margin-top: 4px;
}
}
}
.anticon {
margin-right: 10px;
}
&__label {
margin-bottom: 5px;
font-weight: bold;
}
}
.ant-btn .ant-btn__progress-overlay {
position: absolute;
width: 100%;
height: 100%;
z-index: 5;
opacity: 0.3;
transition: all 0s ease;
position: absolute;
left: 0;
top: 0;
background-color: #666;
}
</style>