show mail attachments in frontend
This commit is contained in:
parent
d1626d1777
commit
04f774404a
11 changed files with 252 additions and 23 deletions
|
@ -29,6 +29,7 @@
|
|||
"vue-router": "^3.1.3",
|
||||
"vuex": "^3.1.2",
|
||||
"vuex-router-sync": "^5.0.0",
|
||||
"vuex-shared-mutations": "^1.0.2",
|
||||
"yarn": "^1.22.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
48
web/src/components/AuthenticatedDataLink.vue
Normal file
48
web/src/components/AuthenticatedDataLink.vue
Normal file
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<a :href="image_data">{{ download }}</a>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
import {mapActions} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "AuthenticatedDataLink",
|
||||
props: {
|
||||
href: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
download: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "unnamed"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
image_data: "",
|
||||
servers: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchImage']),
|
||||
loadImage() {
|
||||
this.fetchImage(this.href).then((response) => {
|
||||
const mime_type = response.headers.get("content-type");
|
||||
response.arrayBuffer().then((buf) => {
|
||||
const base64 = btoa(new Uint8Array(buf)
|
||||
.reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
||||
this.image_data = "data:" + mime_type + ";base64," + base64;
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadImage();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -18,6 +18,14 @@
|
|||
<font-awesome-icon icon="user"/>
|
||||
</button-->
|
||||
</div>
|
||||
<div class="card-footer" v-if="item.attachments.length">
|
||||
<ul>
|
||||
<li v-for="attachment in item.attachments">
|
||||
<AuthenticatedImage :src="`/media/2/256/${attachment.hash}/`" :alt="attachment.name" v-if="attachment.mime_type.startsWith('image/')"/>
|
||||
<AuthenticatedDataLink :href="`/media/2/256/${attachment.hash}/`" :download="attachment.name" v-else/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!--button class="show-replies">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-forward"
|
||||
|
@ -44,8 +52,12 @@
|
|||
|
||||
<script>
|
||||
|
||||
import AuthenticatedImage from "@/components/AuthenticatedImage.vue";
|
||||
import AuthenticatedDataLink from "@/components/AuthenticatedDataLink.vue";
|
||||
|
||||
export default {
|
||||
name: 'TimelineMail',
|
||||
components: {AuthenticatedImage, AuthenticatedDataLink},
|
||||
props: {
|
||||
'item': {
|
||||
type: Object,
|
||||
|
|
|
@ -7,6 +7,7 @@ import router from '../router';
|
|||
import * as base64 from 'base-64';
|
||||
import * as utf8 from 'utf8';
|
||||
import {ticketStateColorLookup, ticketStateIconLookup} from "@/utils";
|
||||
import createMutationsSharer from "vuex-shared-mutations";
|
||||
|
||||
Vue.use(Vuex);
|
||||
const axios = AxiosBootstrap.create({
|
||||
|
@ -103,7 +104,6 @@ const store = new Vuex.Store({
|
|||
slug: slug,
|
||||
text: 'Unknown'
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
isLoggedIn(state) {
|
||||
|
@ -273,10 +273,11 @@ const store = new Vuex.Store({
|
|||
//async verifyToken({commit, state}) {
|
||||
async afterLogin({dispatch}) {
|
||||
const boxes = dispatch('loadBoxes');
|
||||
const states = dispatch('fetchTicketStates');
|
||||
const items = dispatch('loadEventItems');
|
||||
const tickets = dispatch('loadTickets');
|
||||
const user = dispatch('loadUserInfo');
|
||||
await Promise.all([boxes, items, tickets, user]);
|
||||
await Promise.all([boxes, items, tickets, user, states]);
|
||||
},
|
||||
async fetchImage({state}, url) {
|
||||
return await fetch(url, {headers: {'Authorization': `Token ${state.token}`}});
|
||||
|
@ -394,7 +395,31 @@ const store = new Vuex.Store({
|
|||
const {data} = await axios.patch(`/2/tickets/${id}/`, ticket);
|
||||
commit('updateTicket', data);
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [createMutationsSharer({
|
||||
predicate: [
|
||||
'replaceLoadedItems',
|
||||
'setItemCache',
|
||||
'setLayout',
|
||||
'replaceBoxes',
|
||||
'updateItem',
|
||||
'removeItem',
|
||||
'appendItem',
|
||||
'replaceTickets',
|
||||
'replaceUsers',
|
||||
'replaceGroups',
|
||||
'updateTicket',
|
||||
'openAddBoxModal',
|
||||
'closeAddBoxModal',
|
||||
'createToast',
|
||||
'removeToast',
|
||||
'setRemember',
|
||||
'setUser',
|
||||
'setPermissions',
|
||||
'setToken',
|
||||
'logout',
|
||||
]
|
||||
})],
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue