178 lines
4.9 KiB
Vue
178 lines
4.9 KiB
Vue
<template>
|
|
<div class="single-ticket">
|
|
<div class="header-bar">
|
|
<button @click="back">
|
|
{{ t('upschooling', 'Zurück') }}
|
|
</button>
|
|
<button @click="save">
|
|
{{ t('upschooling', 'Speichern') }}
|
|
</button>
|
|
</div>
|
|
<h2>Ticket "ding"</h2>
|
|
<KeyValueTable :data-rows="{Id: ticket.ticketId, Name: ticket.title, Status: ticket.status, Geaendert: toLocaleDate(ticket.lastModified)}" />
|
|
<br>
|
|
<label for="description">{{ t('upschooling', 'Beschreibung') }}</label>
|
|
<textarea id="description" v-model.trim.lazy="description" rows="15" />
|
|
<br>
|
|
<button @click="save">
|
|
{{ t('upschooling', 'Speichern') }}
|
|
</button>
|
|
<hr>
|
|
<iframe id="element-web-frame"
|
|
src="about:blank"
|
|
title="Embedded Element Web"
|
|
width="100%"
|
|
height="400" />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import KeyValueTable from './components/KeyValueTable'
|
|
import axios from '@nextcloud/axios'
|
|
|
|
export default {
|
|
name: 'Ticket',
|
|
components: { KeyValueTable },
|
|
props: {
|
|
ticket: {
|
|
type: Object,
|
|
default() {
|
|
return {}
|
|
},
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
description: this.ticket.description,
|
|
}
|
|
},
|
|
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(e) Helfer*in 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
|
|
}
|
|
}
|
|
})
|
|
},
|
|
methods: {
|
|
toLocaleDate(timestamp) {
|
|
const date = new Date(timestamp)
|
|
return date.toLocaleString()
|
|
},
|
|
|
|
save() {
|
|
this.$emit('save-ticket', this.ticket.ticketId, {}) // TODO: give it only the changed data
|
|
},
|
|
|
|
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,
|
|
}, true)
|
|
|
|
// remove elements by CSS injection
|
|
const styleElement = elementWebFrame.contentDocument.createElement('style')
|
|
styleElement.innerText = `
|
|
.mx_LeftPanel_outerWrapper {
|
|
display: none !important;
|
|
}
|
|
.mx_NewRoomIntro {
|
|
display: none !important;
|
|
}
|
|
.mx_ToastContainer {
|
|
display: none !important;
|
|
}
|
|
`
|
|
elementWebFrame.contentDocument.head.appendChild(styleElement)
|
|
}).catch(console.error)
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
textarea {
|
|
width: 100%;
|
|
margin: 0;
|
|
resize: vertical;
|
|
}
|
|
|
|
.placeholder {
|
|
height: 400px;
|
|
width: 100%;
|
|
background: #f0f0f0;
|
|
}
|
|
|
|
.header-bar {
|
|
display: flex;
|
|
width: 100%;
|
|
flex-direction: row-reverse;
|
|
}
|
|
</style>
|