Skip to content

Commit

Permalink
Feat(Conversation): replace OC dialog with NcDialog
Browse files Browse the repository at this point in the history
Signed-off-by: DorraJaouad <[email protected]>
  • Loading branch information
DorraJaouad committed Nov 8, 2023
1 parent 4e2ff0c commit c21fa0e
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
-->

<template>
<NcAppSettingsDialog :aria-label="t('spreed', 'Conversation settings')"
<NcAppSettingsDialog id="conversation-settings-container"
:aria-label="t('spreed', 'Conversation settings')"
:name="t('spreed', 'Conversation settings')"
:open.sync="showSettings"
:show-navigation="true"
Expand Down
145 changes: 96 additions & 49 deletions src/components/ConversationSettings/DangerZone.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,23 @@
{{ t('spreed', 'Permanently delete this conversation.') }}
</p>
<NcButton type="error"
@click="deleteConversation">
@click="toggleShowDeleteConversationDialog">
{{ t('spreed', 'Delete conversation') }}
</NcButton>
<NcDialog class="danger-zone__dialog"
:open.sync="isDeleteConversationDialogOpen"
:name="t('spreed','Delete Conversation')"
:message="deleteConversationDialogMessage"
:container="container">
<template #actions>
<NcButton type="tertiary" @click="toggleShowDeleteConversationDialog">
{{ t('spreed', 'No') }}
</NcButton>
<NcButton type="error" @click="deleteConversation">
{{ t('spreed', 'Yes') }}
</NcButton>
</template>
</NcDialog>
</div>
<div v-if="canDeleteConversation" class="app-settings-subsection">
<h4 class="app-settings-section__subtitle">
Expand All @@ -56,9 +70,23 @@
{{ t('spreed', 'Permanently delete all the messages in this conversation.') }}
</p>
<NcButton type="error"
@click="clearChatHistory">
@click="toggleShowDeleteChatDialog">
{{ t('spreed', 'Delete chat messages') }}
</NcButton>
<NcDialog class="danger-zone__dialog"
:open.sync="isDeleteChatDialogOpen"
:name="t('spreed','Delete all chat messages')"
:message="deleteChatDialogMessage"
:container="container">
<template #actions>
<NcButton type="tertiary" @click="toggleShowDeleteChatDialog">
{{ t('spreed', 'No') }}
</NcButton>
<NcButton type="error" @click="clearChatHistory">
{{ t('spreed', 'Yes') }}
</NcButton>
</template>
</NcDialog>
</div>
<div />
</div>
Expand All @@ -70,14 +98,17 @@ import { showError } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'

export default {
name: 'DangerZone',
components: {
NcButton,
NcNoteCard,
NcDialog,
},

props: {
conversation: {
type: Object,
Expand All @@ -95,10 +126,35 @@ export default {
},
},

data() {
return {
isDeleteConversationDialogOpen: false,
isDeleteChatDialogOpen: false,
}
},

computed: {
container() {
return '#conversation-settings-container'
},

token() {
return this.conversation.token
},

deleteConversationDialogMessage() {
return t('spreed', 'Do you really want to delete "{displayName}"?', this.conversation, undefined, {
escape: false,
sanitize: false,
})
},

deleteChatDialogMessage() {
return t('spreed', 'Do you really want to delete all messages in "{displayName}"?', this.conversation, undefined, {
escape: false,
sanitize: false,
})
}
},

methods: {
Expand Down Expand Up @@ -126,59 +182,44 @@ export default {
* Deletes the conversation.
*/
async deleteConversation() {
OC.dialogs.confirm(
t('spreed', 'Do you really want to delete "{displayName}"?', this.conversation, undefined, {
escape: false,
sanitize: false,
}),
t('spreed', 'Delete conversation'),
async function(decision) {
if (!decision) {
return
}

if (this.token === this.$store.getters.getToken()) {
this.$router.push({ name: 'root' })
this.$store.dispatch('updateToken', '')
}

try {
await this.$store.dispatch('deleteConversationFromServer', { token: this.token })
// Close the settings
this.hideConversationSettings()
} catch (error) {
console.debug(`error while deleting conversation ${error}`)
showError(t('spreed', 'Error while deleting conversation'))
}
}.bind(this)
)
this.isDeleteConversationDialogOpen = false

if (this.token === this.$store.getters.getToken()) {
this.$router.push({ name: 'root' })
this.$store.dispatch('updateToken', '')
}

try {
await this.$store.dispatch('deleteConversationFromServer', { token: this.token })
// Close the settings
this.hideConversationSettings()
} catch (error) {
console.debug(`error while deleting conversation ${error}`)
showError(t('spreed', 'Error while deleting conversation'))
}
},

/**
* Clears the chat history
*/
async clearChatHistory() {
OC.dialogs.confirm(
t('spreed', 'Do you really want to delete all messages in "{displayName}"?', this.conversation, undefined, {
escape: false,
sanitize: false,
}),
t('spreed', 'Delete all chat messages'),
async function(decision) {
if (!decision) {
return
}

try {
await this.$store.dispatch('clearConversationHistory', { token: this.token })
// Close the settings
this.hideConversationSettings()
} catch (error) {
console.debug(`error while clearing chat history ${error}`)
showError(t('spreed', 'Error while clearing chat history'))
}
}.bind(this)
)
try {
await this.$store.dispatch('clearConversationHistory', { token: this.token })
this.isDeleteChatDialogOpen = false
// Close the settings
this.hideConversationSettings()
} catch (error) {
console.debug(`error while clearing chat history ${error}`)
showError(t('spreed', 'Error while clearing chat history'))
}
},

toggleShowDeleteConversationDialog() {
this.isDeleteConversationDialogOpen = !this.isDeleteConversationDialogOpen
},

toggleShowDeleteChatDialog() {
this.isDeleteChatDialogOpen = !this.isDeleteChatDialogOpen
},
},
}
Expand All @@ -193,6 +234,12 @@ h4 {
&__hint {
color: var(--color-text-maxcontrast);
}
&__dialog {
:deep(.modal-container) {
padding-block: 4px 8px;
padding-inline: 12px 8px;
}
}
}

</style>
70 changes: 60 additions & 10 deletions src/components/LeftSidebar/ConversationsList/Conversation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { showSuccess, showError } from '@nextcloud/dialogs'

import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'

import Conversation from './Conversation.vue'

Expand Down Expand Up @@ -400,48 +402,96 @@ describe('Conversation.vue', () => {

describe('deleting conversation', () => {
test('deletes conversation when confirmed', async () => {
// Arrange
const actionHandler = jest.fn().mockResolvedValueOnce()
const updateTokenAction = jest.fn()
testStoreConfig.modules.conversationsStore.actions.deleteConversationFromServer = actionHandler
testStoreConfig.modules.tokenStore.getters.getToken = jest.fn().mockReturnValue(() => 'another-token')
testStoreConfig.modules.tokenStore.actions.updateToken = updateTokenAction

OC.dialogs.confirm = jest.fn()
const wrapper = shallowMount(Conversation, {
localVue,
store: new Vuex.Store(testStoreConfig),
mocks: {
$router,
},
stubs: {
NcActionButton,
NcDialog,
NcButton,
},
propsData: {
isSearchResult: false,
item,
},
})
const el = wrapper.findComponent({ name: 'NcListItem' })

const action = shallowMountAndGetAction('Delete conversation')
const action = findNcActionButton(el, 'Delete conversation')
expect(action.exists()).toBe(true)

// Act 1 : click on the button from the menu
await action.find('button').trigger('click')

expect(OC.dialogs.confirm).toHaveBeenCalled()
// Assert 1
const dialog = wrapper.findComponent({ name: 'NcDialog' })
expect(dialog.exists).toBeTruthy()
const buttons = dialog.findAllComponents({ name: 'NcButton' })
expect(buttons.exists()).toBeTruthy()
expect(buttons).toHaveLength(2)

// call callback directly
OC.dialogs.confirm.mock.calls[0][2](true)
// Act 2 : click on the confirm button
await buttons.at(1).find('button').trigger('click')

// Assert 2
expect(actionHandler).toHaveBeenCalledWith(expect.anything(), { token: TOKEN })
expect($router.push).not.toHaveBeenCalled()
expect(updateTokenAction).not.toHaveBeenCalled()
})

test('does not delete conversation when not confirmed', async () => {
// Arrange
const actionHandler = jest.fn().mockResolvedValueOnce()
const updateTokenAction = jest.fn()
testStoreConfig.modules.conversationsStore.actions.deleteConversationFromServer = actionHandler
testStoreConfig.modules.tokenStore.getters.getToken = jest.fn().mockReturnValue(() => 'another-token')
testStoreConfig.modules.tokenStore.actions.updateToken = updateTokenAction

OC.dialogs.confirm = jest.fn()
const wrapper = shallowMount(Conversation, {
localVue,
store: new Vuex.Store(testStoreConfig),
mocks: {
$router,
},
stubs: {
NcActionButton,
NcDialog,
NcButton,
},
propsData: {
isSearchResult: false,
item,
},
})
const el = wrapper.findComponent({ name: 'NcListItem' })

const action = shallowMountAndGetAction('Delete conversation')
const action = findNcActionButton(el, 'Delete conversation')
expect(action.exists()).toBe(true)

// Act 1 : click on the button from the menu
await action.find('button').trigger('click')

expect(OC.dialogs.confirm).toHaveBeenCalled()
// Assert 1
const dialog = wrapper.findComponent({ name: 'NcDialog' })
expect(dialog.exists).toBeTruthy()
const buttons = dialog.findAllComponents({ name: 'NcButton' })
expect(buttons.exists()).toBeTruthy()
expect(buttons).toHaveLength(2)

// call callback directly
OC.dialogs.confirm.mock.calls[0][2](false)
// Act 2 : click on the confirm button
await buttons.at(0).find('button').trigger('click')

// Assert 2
expect(actionHandler).not.toHaveBeenCalled()
expect($router.push).not.toHaveBeenCalled()
expect(updateTokenAction).not.toHaveBeenCalled()
Expand Down
Loading

0 comments on commit c21fa0e

Please sign in to comment.