2019-05-14 01:15:45 +02:00
<!--
- @ copyright Copyright ( c ) 2018 René Gieling < github @ dartcafe.de >
-
- @ author Ajfar Huq
- @ author Nick Gallo
- @ author Affan Hussain
-
- @ license GNU AGPL version 3 or any later version
-
- This program is free software : you can redistribute it and / or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation , either version 3 of the
- License , or ( at your option ) any later version .
-
- This program is distributed in the hope that it will be useful ,
- but WITHOUT ANY WARRANTY ; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
- GNU Affero General Public License for more details .
-
- You should have received a copy of the GNU Affero General Public License
- along with this program . If not , see < http : / / www.gnu.org / licenses / > .
-
-- >
< template >
2020-04-24 15:37:46 +02:00
< AppContent v-if ="loadingResults" >
< EmptyContent icon = "icon-loading" >
2020-04-25 00:31:03 +02:00
{ { t ( 'forms' , 'Loading responses …' ) } }
2020-04-24 15:37:46 +02:00
< / EmptyContent >
< / AppContent >
< AppContent v-else >
< TopBar >
< button @click ="showEdit" >
< span class = "icon-forms" role = "img" / >
{ { t ( 'forms' , 'Back to form' ) } }
2019-05-14 01:15:45 +02:00
< / button >
2020-04-24 15:37:46 +02:00
< / TopBar >
< header v-if ="!noSubmissions" >
2020-04-25 00:31:03 +02:00
< h2 > { { t ( 'forms' , 'Responses for {title}' , { title : form . title } ) } } < / h2 >
2020-04-23 15:06:04 +02:00
< div v-for ="sum in stats" :key ="sum" >
{ { sum } }
< / div >
2020-04-24 15:37:46 +02:00
< / header >
<!-- No submissions -- >
< section v-if ="noSubmissions" >
2020-04-25 00:31:03 +02:00
< EmptyContent icon = "icon-comment" >
{ { t ( 'forms' , 'No responses yet' ) } }
< template # desc >
{ { t ( 'forms' , 'Results of submitted forms will show up here' ) } }
< / template >
2020-04-24 15:37:46 +02:00
<!-- Button to copy Share - Link ? -- >
< / EmptyContent >
< / section >
< section v-else >
< button id = "exportButton" class = "primary" @click ="download" >
< span class = "icon-download-white" role = "img" / >
{ { t ( 'forms' , 'Export to CSV' ) } }
< / button >
< transition -group
name = "list"
tag = "div"
class = "table" >
< ResultItem
key = "0"
: header = "true" / >
< ResultItem
v - for = "answer in answers"
: key = "answer.id"
: answer = "answer" / >
< / t r a n s i t i o n - g r o u p >
< / section >
2020-03-20 12:22:07 +01:00
< / AppContent >
2019-05-14 01:15:45 +02:00
< / template >
< script >
2020-04-24 15:37:46 +02:00
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
2020-02-25 20:28:30 +01:00
import axios from '@nextcloud/axios'
2020-04-29 11:23:08 +02:00
import json2csvParser from 'json2csv'
2020-04-24 15:37:46 +02:00
import EmptyContent from '../components/EmptyContent'
2020-04-29 11:23:08 +02:00
import ResultItem from '../components/resultItem'
2020-04-24 15:37:46 +02:00
import TopBar from '../components/TopBar'
2020-03-20 12:22:07 +01:00
import ViewsMixin from '../mixins/ViewsMixin'
2019-05-14 01:15:45 +02:00
export default {
name : 'Results' ,
components : {
2020-03-20 12:22:07 +01:00
AppContent ,
2020-04-24 15:37:46 +02:00
EmptyContent ,
2020-02-26 14:00:27 +01:00
ResultItem ,
2020-04-24 15:37:46 +02:00
TopBar ,
2019-05-14 01:15:45 +02:00
} ,
2020-03-20 12:22:07 +01:00
mixins : [ ViewsMixin ] ,
2019-05-14 01:15:45 +02:00
data ( ) {
return {
2020-04-24 15:37:46 +02:00
loadingResults : true ,
2020-03-30 13:48:14 +02:00
answers : [ ] ,
2019-05-14 01:15:45 +02:00
}
} ,
2019-09-03 10:32:32 +02:00
computed : {
stats ( ) {
2020-02-26 14:00:27 +01:00
const sums = [ ]
2019-09-03 10:32:32 +02:00
2020-03-30 13:48:14 +02:00
if ( this . answers != null ) {
2020-02-26 13:39:50 +01:00
const uniqueAns = [ ]
const uniqueQs = [ ]
const ansToQ = new Map ( )
2020-03-30 13:48:14 +02:00
for ( let i = 0 ; i < this . answers . length ; i ++ ) {
if ( this . answers [ i ] . questionType === 'radiogroup' || this . answers [ i ] . questionType === 'dropdown' ) {
if ( uniqueAns . includes ( this . answers [ i ] . text ) === false ) {
uniqueAns . push ( this . answers [ i ] . text )
ansToQ . set ( this . answers [ i ] . text , this . answers [ i ] . questionId )
2019-09-03 10:32:32 +02:00
}
2020-03-30 13:48:14 +02:00
if ( uniqueQs . includes ( this . answers [ i ] . questionId ) === false ) {
uniqueQs . push ( this . answers [ i ] . questionId )
2019-09-03 10:32:32 +02:00
}
}
}
for ( let i = 0 ; i < uniqueAns . length ; i ++ ) {
sums [ i ] = 0
}
2020-03-30 13:48:14 +02:00
for ( let i = 0 ; i < this . answers . length ; i ++ ) {
sums [ uniqueAns . indexOf ( this . answers [ i ] . text ) ] ++
2019-09-03 10:32:32 +02:00
}
for ( let i = 0 ; i < sums . length ; i ++ ) {
2020-03-30 13:48:14 +02:00
sums [ i ] = 'Question ' + ansToQ . get ( uniqueAns [ i ] ) + ': ' + ( sums [ i ] / ( ( this . answers . length / uniqueQs . length ) ) * 100 ) . toFixed ( 2 ) + '%' + ' of respondents voted for answer choice: ' + uniqueAns [ i ]
2019-09-03 10:32:32 +02:00
}
}
2020-02-26 14:00:27 +01:00
2019-09-03 10:32:32 +02:00
return sums . sort ( )
2020-02-26 13:39:50 +01:00
} ,
2020-04-24 15:37:46 +02:00
noSubmissions ( ) {
return this . answers && this . answers . length === 0
} ,
2019-09-03 10:32:32 +02:00
} ,
2020-04-24 15:37:46 +02:00
beforeMount ( ) {
this . loadFormResults ( )
2019-05-14 01:15:45 +02:00
} ,
methods : {
2020-04-24 15:37:46 +02:00
showEdit ( ) {
2019-05-14 01:15:45 +02:00
this . $router . push ( {
2020-04-24 15:37:46 +02:00
name : 'edit' ,
2019-05-14 01:15:45 +02:00
params : {
2020-04-24 15:37:46 +02:00
hash : this . form . hash ,
2020-02-26 13:39:50 +01:00
} ,
2019-05-14 01:15:45 +02:00
} )
} ,
2020-04-24 15:37:46 +02:00
async loadFormResults ( ) {
this . loadingResults = true
console . debug ( 'Loading Results' )
try {
const response = await axios . get ( generateUrl ( '/apps/forms/api/v1/submissions/{hash}' , {
hash : this . form . hash ,
} ) )
this . answers = response . data
console . debug ( this . answers )
} catch ( error ) {
console . error ( error )
showError ( t ( 'forms' , 'There was an error while loading results' ) )
} finally {
this . loadingResults = false
}
} ,
download ( ) {
2019-05-14 09:03:59 +02:00
this . loading = true
2020-04-29 11:23:08 +02:00
axios . get ( generateUrl ( 'apps/forms/get/form/' + this . $route . params . hash ) )
2019-05-14 09:03:59 +02:00
. then ( ( response ) => {
2020-03-30 13:48:14 +02:00
this . json2csvParser = [ 'userId' , 'questionId' , 'questionText' , 'Answer' ] // TODO Is this one necessary??
const formattedAns = [ ]
this . answers . forEach ( ans => {
formattedAns . push ( {
userId : ans [ 'userId' ] ,
questionId : ans [ 'questionId' ] ,
questionText : ans [ 'questionText' ] ,
answer : ans [ 'text' ] ,
} )
} )
2020-02-26 13:39:50 +01:00
const element = document . createElement ( 'a' )
2020-03-30 13:48:14 +02:00
element . setAttribute ( 'href' , 'data:text/csv;charset=utf-8,' + encodeURIComponent ( json2csvParser . parse ( formattedAns ) ) )
2019-05-14 09:03:59 +02:00
element . setAttribute ( 'download' , response . data . title + '.csv' )
element . style . display = 'none'
document . body . appendChild ( element )
element . click ( )
document . body . removeChild ( element )
this . loading = false
} , ( error ) => {
/* eslint-disable-next-line no-console */
console . log ( error . response )
this . loading = false
} )
2020-02-26 13:39:50 +01:00
} ,
} ,
2019-05-14 01:15:45 +02:00
}
< / script >
2020-04-24 15:37:46 +02:00
< style lang = "scss" scoped >
2019-05-14 01:15:45 +02:00
. table {
width : 100 % ;
margin - top : 45 px ;
display : flex ;
flex - direction : column ;
flex - grow : 1 ;
flex - wrap : nowrap ;
}
2020-04-24 15:37:46 +02:00
# exportButton {
width : max - content ;
2019-05-14 01:15:45 +02:00
}
< / style >