This commit is contained in:
Peter Howell 2025-09-26 21:12:44 +00:00
parent 3986f90a83
commit 8d1c5b794c
2 changed files with 77 additions and 27 deletions

View File

@ -2056,39 +2056,39 @@ const ActivityInfoReport2 = Vue.component('activityinforeport2', {
watch: { }, watch: { },
template: `<div class="bg-white rounded-md shadow-md p-6 text-sm text-gray-800 space-y-4"> template: `<div class="bg-white rounded-md shadow-md p-6 text-sm text-gray-800 space-y-4">
<!-- Title --> <!-- Title -->
<table class="w-full border-collapse text-sm"> <table class="w-full border-collapse table-fixed text-sm">
<tbody> <tbody>
<tr> <tr>
<th class="text-left align-top pr-4 py-1 w-32">Title:</th> <th class="text-left align-top pr-4 py-1 w-32">Title:</th>
<td class="py-1 font-semibold">{{ a.title }}</td> <td class="py-1 font-semibold break-words break-all">{{ a.title }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Date:</th> <th class="text-left align-top pr-4 py-1">Date:</th>
<td class="py-1">{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }}</td> <td class="py-1 break-words break-all">{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Mode / Location:</th> <th class="text-left align-top pr-4 py-1">Mode / Location:</th>
<td class="py-1"> <td class="py-1 break-words break-all">
{{ mode_string(a) }} {{ mode_string(a) }}
<div v-if="a.location" class="text-gray-600">{{ a.location }}</div> <div v-if="a.location" class="text-gray-600 break-words break-all">{{ a.location }}</div>
<div v-if="a.location_irl" class="text-gray-600">{{ a.location_irl }}</div> <div v-if="a.location_irl" class="text-gray-600 break-words break-all">{{ a.location_irl }}</div>
</td> </td>
</tr> </tr>
<tr v-if="a.desc"> <tr v-if="a.desc">
<th class="text-left align-top pr-4 py-1">Description:</th> <th class="text-left align-top pr-4 py-1">Description:</th>
<td class="py-1" v-html="a.desc"></td> <td class="py-1 break-words break-all" v-html="a.desc"></td>
</tr> </tr>
<tr v-if="host"> <tr v-if="host">
<th class="text-left align-top pr-4 py-1">Hosts:</th> <th class="text-left align-top pr-4 py-1">Hosts:</th>
<td class="py-1">{{ host }}</td> <td class="py-1 break-words break-all">{{ host }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Attendees:</th> <th class="text-left align-top pr-4 py-1">Attendees:</th>
<td class="py-1">{{ user }}</td> <td class="py-1 break-words break-all">{{ user }}</td>
</tr> </tr>
<tr v-if="survey"> <tr v-if="survey">
<th class="text-left align-top pr-4 py-1">Survey Results:</th> <th class="text-left align-top pr-4 py-1">Survey Results:</th>
<td class="py-1" v-html="survey"></td> <td class="py-1 break-words break-all" v-html="survey"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -2102,39 +2102,39 @@ const ActivityInfoReportTable = Vue.component('activityinforeport_table', {
mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] }, mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] },
}, },
template: `<div class="bg-white rounded-md shadow-md p-4 text-sm text-gray-800 space-y-2"> template: `<div class="bg-white rounded-md shadow-md p-4 text-sm text-gray-800 space-y-2">
<table class="w-full border-collapse"> <table class="w-full border-collapse table-fixed">
<tbody> <tbody>
<tr> <tr>
<th class="text-left align-top pr-4 py-1 w-28">Title:</th> <th class="text-left align-top pr-4 py-1 w-28">Title:</th>
<td class="py-1 font-semibold">{{ a.title }}</td> <td class="py-1 font-semibold break-words break-all">{{ a.title }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Date:</th> <th class="text-left align-top pr-4 py-1">Date:</th>
<td class="py-1">{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }}</td> <td class="py-1 break-words break-all">{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Mode / Location:</th> <th class="text-left align-top pr-4 py-1">Mode / Location:</th>
<td class="py-1"> <td class="py-1 break-words break-all">
{{ mode_string(a) }} {{ mode_string(a) }}
<div v-if="a.location">{{ a.location }}</div> <div v-if="a.location" class="break-words break-all">{{ a.location }}</div>
<div v-if="a.location_irl">{{ a.location_irl }}</div> <div v-if="a.location_irl" class="break-words break-all">{{ a.location_irl }}</div>
</td> </td>
</tr> </tr>
<tr v-if="a.desc"> <tr v-if="a.desc">
<th class="text-left align-top pr-4 py-1">Description:</th> <th class="text-left align-top pr-4 py-1">Description:</th>
<td class="py-1" v-html="a.desc"></td> <td class="py-1 break-words break-all" v-html="a.desc"></td>
</tr> </tr>
<tr v-if="host"> <tr v-if="host">
<th class="text-left align-top pr-4 py-1">Hosts:</th> <th class="text-left align-top pr-4 py-1">Hosts:</th>
<td class="py-1">{{ host }}</td> <td class="py-1 break-words break-all">{{ host }}</td>
</tr> </tr>
<tr> <tr>
<th class="text-left align-top pr-4 py-1">Attendees:</th> <th class="text-left align-top pr-4 py-1">Attendees:</th>
<td class="py-1">{{ user }}</td> <td class="py-1 break-words break-all">{{ user }}</td>
</tr> </tr>
<tr v-if="survey"> <tr v-if="survey">
<th class="text-left align-top pr-4 py-1">Survey Results:</th> <th class="text-left align-top pr-4 py-1">Survey Results:</th>
<td class="py-1" v-html="survey"></td> <td class="py-1 break-words break-all" v-html="survey"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -2248,18 +2248,50 @@ const ActivityReport = Vue.component('activityreport', {
var result = "" var result = ""
if (this.answers2[id]) { if (this.answers2[id]) {
_.each( this.answers2[id], function (qlist) { _.each( this.answers2[id], function (qlist) {
result += "<b class='survey_q'>" + qlist[0]['question'] + "</b><br />\n<ul>" // try to build numeric histogram 15
var nums = []
_.each( qlist, function(qanswer) { _.each( qlist, function(qanswer) {
result += "<li>" + qanswer['answer'] + "</li>\n" var v = parseInt(qanswer['answer'])
if (!isNaN(v) && v>=1 && v<=5) { nums.push(v) }
}) })
result += "</ul>\n" result += "<div style=\"margin:8px 0;\">"
result += "<b class='survey_q'>" + qlist[0]['question'] + "</b><br/>"
if (nums.length) {
var counts = [0,0,0,0,0,0] // index 1..5
var sum = 0
_.each(nums, function(v){ counts[v]+=1; sum+=v })
var maxc = _.max(counts.slice(1)) || 1
var avg = (sum/nums.length).toFixed(2)
// table-based bars with inline width; good for copy/paste
result += "<table style=\"border-collapse:collapse; margin-top:4px;\">"
for (var i=1;i<=5;i++) {
var c = counts[i]
var width = Math.round((c/maxc)*200) // px
result += "<tr>"
+ "<td style=\"padding:2px 6px 2px 0; font-weight:600; color:#374151;\">"+i+"</td>"
+ "<td style=\"padding:2px 6px;\">"
+ "<div style=\"width:200px; height:10px; background:#e5e7eb; display:inline-block; vertical-align:middle;\">"
+ "<div style=\"height:10px; width:"+width+"px; background:#3b82f6;\"></div>"
+ "</div>"
+ "<span style=\"display:inline-block; min-width:28px; margin-left:6px; color:#374151;\">"+c+"</span>"
+ "</td>"
+ "</tr>"
}
result += "</table>"
result += "<div style=\"font-size:12px; color:#6b7280; margin-top:2px;\">Responses: "+nums.length+", Average: "+avg+"</div>"
} else {
// fallback: list non-numeric answers
result += "<ul>"
_.each( qlist, function(qanswer) {
result += "<li>" + (qanswer['answer']||'') + "</li>\n"
})
result += "</ul>\n"
}
result += "</div>"
}) })
return result return result
} }
return "<i>no survey results?</i>" return "<i>no survey results?</i>"
var answers = _.find(this.activities, function(x) { return x.id == id } )
return "Surveys"
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '')
}, },
}, },
computed: { computed: {

View File

@ -41,3 +41,21 @@ ol {
list-style-type: decimal!important; list-style-type: decimal!important;
list-style-position: inside!important; list-style-position: inside!important;
} }
/* Report page: prevent long URLs or tokens from causing horizontal scroll */
.activityreport {
overflow-wrap: anywhere;
word-break: break-word;
}
.activityreport table,
.activityreport td,
.activityreport th,
.activityreport p,
.activityreport li,
.activityreport div,
.activityreport span,
.activityreport a,
.activityreport code {
overflow-wrap: anywhere;
word-break: break-word;
}