Skip to content

Commit

Permalink
[UXE-3320] refactor: service unbinding treated as deletion in edge no…
Browse files Browse the repository at this point in the history
…de (#1555)

* feat: create unbind dialog

* feat: make list table handle inbiding action

* fix: adjust component to set correct props for unbinding

* test: adjust unit test

* style: lint formatting

* refactor: general improvements after CR
  • Loading branch information
william-tome authored Jul 30, 2024
1 parent c113f38 commit 5fed5ed
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const deleteServiceEdgeNodeService = async ({ edgeNodeId, id }) => {
const parseHttpResponse = (httpResponse) => {
switch (httpResponse.statusCode) {
case 204:
return 'Service on Edge Node successfully deleted'
return 'Service successfully unbound'
case 400:
throw new Errors.NotFoundError().message
case 401:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('EdgeNodeServices', () => {

const feedbackMessage = await sut(mockId)

expect(feedbackMessage).toBe('Service on Edge Node successfully deleted')
expect(feedbackMessage).toBe('Service successfully unbound')
})

it.each([
Expand Down
162 changes: 162 additions & 0 deletions src/views/EdgeNode/Dialog/Unbind.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<template>
<PrimeDialog
blockScroll
modal
visible
:header="`Unbind ${data.title}`"
:draggable="false"
class="max-w-2xl"
@keyup.enter="removeItem()"
data-testid="unbind-dialog__header"
>
<div
class="flex flex-col gap-6"
data-testid="unbind-dialog__content__wrapper"
>
<div data-testid="unbind-dialog__warning__wrapper">
<Message
severity="warn"
:closable="false"
data-testid="unbind-dialog__warning__inline-message"
>
Once confirmed, this action can't be reversed.
</Message>

<p
class="pt-4 text-color-secondary"
data-testid="unbind-dialog__warning__message-details"
>
This {{ data.title }} will be unbound from the {{ data.parent }}, along with any
associated settings.
</p>
</div>

<div data-testid="unbind-dialog__confirmation__wrapper">
<div
class="flex flex-col w-full gap-2"
data-testid="unbind-dialog__confirmation-field__wrapper"
>
<label
for="confirm-input"
class="font-semibold text-sm"
data-testid="unbind-dialog__confirmation-field__label"
>Type “unbind” to confirm:</label
>
<InputText
id="confirm-input"
type="text"
autofocus
v-model="confirmation"
:class="{ 'p-invalid': errors.confirmation }"
data-testid="unbind-dialog__confirmation-field__input"
/>
<small
v-if="errors.confirmation"
class="p-error text-xs font-normal leading-tight"
data-testid="unbind-dialog__confirmation-field__error"
>
{{ errors.confirmation }}
</small>
</div>
</div>
</div>

<template #closeicon>
<PrimeButton
outlined
@click="cancelDialog()"
icon="pi pi-times"
data-testid="unbind-dialog__close-icon__button"
/>
</template>

<template #footer>
<PrimeButton
outlined
label="Cancel"
@click="cancelDialog()"
data-testid="unbind-dialog__footer__cancel-button"
/>
<PrimeButton
severity="danger"
label="Unbind"
icon-pos="right"
@click="removeItem()"
:loading="loading"
:disabled="isDisabled"
data-testid="unbind-dialog__footer__unbind-button"
/>
</template>
</PrimeDialog>
</template>

<script setup>
import { computed, ref, inject } from 'vue'
import { useField, useForm } from 'vee-validate'
import { useToast } from 'primevue/usetoast'
import * as yup from 'yup'
import PrimeButton from 'primevue/button'
import PrimeDialog from 'primevue/dialog'
import InputText from 'primevue/inputtext'
import Message from 'primevue/message'
defineOptions({ name: 'dialog-unbind' })
const toast = useToast()
const dialogRef = inject('dialogRef')
const data = dialogRef.value.data
const loading = ref(false)
const validationSchema = yup.object({
confirmation: yup
.string()
.required('This is a required field')
.test('equals', '', (val) => {
return val === 'unbind'
})
})
const { errors, meta, resetForm } = useForm({
validationSchema,
initialValues: {
confirmation: ''
}
})
const { value: confirmation } = useField('confirmation')
const removeItem = async () => {
if (!meta.value.valid) return
loading.value = true
try {
const feedback = await data.service(data.selectedID)
showToast('success', feedback ?? 'Unbound successfully!')
resetForm()
dialogRef.value.close({ updated: true })
} catch (error) {
showToast('error', 'Error', error)
} finally {
loading.value = false
}
}
const showToast = (severity, summary, detail = '') => {
toast.add({
closable: true,
severity,
summary,
detail
})
}
const cancelDialog = () => {
resetForm()
dialogRef.value.close({ updated: false })
}
const isDisabled = computed(() => {
return !meta.value.valid || loading.value
})
</script>
20 changes: 16 additions & 4 deletions src/views/EdgeNode/ListViewTabServices.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import DrawerService from '@/views/EdgeNode/Drawer'
import PrimeButton from 'primevue/button'
import { computed, ref } from 'vue'
import UnbindDialog from '@/views/EdgeNode/Dialog/Unbind'
defineOptions({ name: 'list-edge-node-resources-tab' })
Expand Down Expand Up @@ -70,7 +71,7 @@
})
}
const deleteServicesWithDecorator = async (id) => {
const unbindServicesWithDecorator = async (id) => {
return await props.deleteServiceEdgeNodeService({
edgeNodeId: props.edgeNodeId,
id
Expand All @@ -87,10 +88,21 @@
const actions = [
{
type: 'delete',
title: 'service',
type: 'dialog',
icon: 'pi pi-trash',
service: deleteServicesWithDecorator
label: 'Unbind',
dialog: {
component: UnbindDialog,
body: (item) => ({
data: {
title: 'edge service',
parent: 'edge node',
selectedID: item.id,
service: unbindServicesWithDecorator
},
onClose: (opt) => opt.data.updated && reloadServicesList()
})
}
}
]
</script>
Expand Down

0 comments on commit 5fed5ed

Please sign in to comment.