Nextcloud-App/src/Ticket.vue

176 lines
5.1 KiB
Vue
Raw Normal View History

<template>
<div class="single-ticket">
2021-08-22 14:37:12 +00:00
<div class="header-bar">
2021-09-18 12:50:21 +00:00
<button @click="back">
2022-02-19 12:17:40 +00:00
{{ t('upschooling', 'Zurück') }}
2021-08-22 14:37:12 +00:00
</button>
2021-09-18 12:50:21 +00:00
<button @click="save">
2021-08-22 14:37:12 +00:00
{{ t('upschooling', 'Speichern') }}
</button>
</div>
<h2>Ticket "ding"</h2>
2021-09-19 14:55:30 +00:00
<KeyValueTable :data-rows="{Id: ticket.ticketId, Name: ticket.title, Status: ticket.status, Geaendert: toLocaleDate(ticket.lastModified)}" />
<br>
2021-08-22 14:37:12 +00:00
<label for="description">{{ t('upschooling', 'Beschreibung') }}</label>
<textarea id="description" v-model.trim.lazy="description" rows="15" />
2021-08-21 17:38:46 +00:00
<br>
2021-08-21 17:58:03 +00:00
<button @click="save">
2021-09-19 14:55:30 +00:00
{{ t('upschooling', 'Speichern') }}
2021-08-21 17:58:03 +00:00
</button>
2021-08-21 17:38:46 +00:00
<hr>
<iframe id="element-web-frame"
src="about:blank"
title="Embedded Element Web"
width="100%"
height="400" />
</div>
</template>
<script>
2021-08-22 14:37:12 +00:00
import KeyValueTable from './components/KeyValueTable'
import axios from '@nextcloud/axios'
export default {
name: 'Ticket',
2021-08-22 14:37:12 +00:00
components: { KeyValueTable },
2021-09-18 12:50:21 +00:00
props: {
ticket: {
type: Object,
default() {
return {}
},
},
},
2021-08-21 17:58:03 +00:00
data() {
return {
2021-09-18 12:50:21 +00:00
description: this.ticket.description,
2021-08-21 17:58:03 +00:00
}
},
mounted() {
/** @type {HTMLIFrameElement} */
const elementWebFrame = document.getElementById('element-web-frame')
this.loadChat(elementWebFrame).catch((err) => {
if (err.message === 'Room not found') {
console.debug('No chat room assigned to ticket')
elementWebFrame.src = 'about:blank'
elementWebFrame.onload = function() {
const textElement = elementWebFrame.contentDocument.createElement('strong')
textElement.innerText = 'Textchat nicht verfügbar. Es ist noch kein Helfer zugewiesen.'
elementWebFrame.contentDocument.body.appendChild(textElement)
elementWebFrame.onload = undefined
}
} else {
console.error('Could not load Element Web in iframe', err)
elementWebFrame.src = 'about:blank'
elementWebFrame.onload = function() {
const textElement = elementWebFrame.contentDocument.createElement('strong')
textElement.innerText = 'Element Web konnte nicht geladen werden.'
elementWebFrame.contentDocument.body.appendChild(textElement)
elementWebFrame.onload = undefined
}
}
})
},
2021-08-21 17:58:03 +00:00
methods: {
2021-09-19 14:55:30 +00:00
toLocaleDate(timestamp) {
const date = new Date(timestamp)
return date.toLocaleString()
},
2021-09-18 12:50:21 +00:00
save() {
2021-09-19 14:55:30 +00:00
this.$emit('save-ticket', this.ticket.ticketId, {}) // TODO: give it only the changed data
2021-09-18 12:50:21 +00:00
},
back() {
this.$emit('show-ticket-list')
},
async loadChat(elementWebFrame) {
const matrixInfoResponse = await axios.get(
`api/v1/tickets/${this.ticket.ticketId}/chat`,
{ headers: { Accept: 'application/json' }, validateStatus: status => status === 200 || status === 404 },
)
if (matrixInfoResponse.status === 404 && matrixInfoResponse.data.message === 'Room not found') {
throw Error(matrixInfoResponse.data.message)
}
if (matrixInfoResponse.status !== 200) {
throw Error(`Received unexpected status code ${matrixInfoResponse.status} for fetching matrix chat data`)
}
if (!matrixInfoResponse.data) {
throw Error('Did not receive any matrix chat data')
}
if (typeof matrixInfoResponse.data !== 'object') {
throw Error('Unexpected return value for fetching matrix chat data')
}
const loginPromise = new Promise(function(resolve, reject) {
const tryLogin = (elementWebFrame, matrixInfo, round) => {
if (elementWebFrame.contentWindow.mxLoginWithAccessToken === undefined) {
console.warn('Couldn\'t login in round ' + round)
setTimeout(() => {
tryLogin(elementWebFrame, matrixInfo, round + 1)
}, 1000)
} else {
elementWebFrame.contentWindow.mxLoginWithAccessToken(
matrixInfo.matrixServerUrl,
matrixInfo.matrixAccessToken,
).then(resolve).catch(reject)
}
}
elementWebFrame.onload = function() {
elementWebFrame.onload = undefined
tryLogin(elementWebFrame, matrixInfoResponse.data, 1)
}
})
// load Element Web
elementWebFrame.src = '/upschooling/element-web/'
loginPromise.then(async () => {
const matrixClient = elementWebFrame.contentWindow.mxMatrixClientPeg.get()
await matrixClient.joinRoom(matrixInfoResponse.data.matrixChatRoom)
elementWebFrame.contentWindow.mxDispatcher.dispatch({
action: 'view_room',
room_id: matrixInfoResponse.data.matrixChatRoom,
2022-04-30 13:39:20 +00:00
}, true)
// removes left panel by DOM manipulation
const matrixchat = elementWebFrame.contentDocument.getElementById('matrixchat')
console.debug(matrixchat)
const observerConfig = { attributes: false, childList: true, subtree: true }
const observer = new MutationObserver((mutationsList, observer) => {
console.debug('observer kicked', observer)
const leftPanelsByClass = elementWebFrame.contentDocument.getElementsByClassName('mx_LeftPanel_outerWrapper')
for (const leftPanel of leftPanelsByClass) {
leftPanel.remove()
}
})
2022-04-30 13:39:20 +00:00
observer.observe(matrixchat, observerConfig)
}).catch(console.error)
},
2021-08-21 17:58:03 +00:00
},
}
</script>
<style scoped>
textarea {
width: 100%;
2021-08-22 14:37:12 +00:00
margin: 0;
resize: vertical;
}
.placeholder {
height: 400px;
width: 100%;
background: #f0f0f0;
}
.header-bar {
display: flex;
width: 100%;
flex-direction: row-reverse;
}
</style>