Finished creating result statistic views
This commit is contained in:
parent
187c52cd44
commit
96d751843a
23
client/src/components/icons/ChevronDoubleRight.vue
Normal file
23
client/src/components/icons/ChevronDoubleRight.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<svg-icon type="mdi" :path="path"></svg-icon>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SvgIcon from '@jamescoyle/vue-icon'
|
||||||
|
import { mdiChevronDoubleRight } from '@mdi/js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "mdiChefronDoubleRight",
|
||||||
|
|
||||||
|
components: {
|
||||||
|
SvgIcon
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
path: mdiChevronDoubleRight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -50,7 +50,7 @@
|
|||||||
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
|
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
|
||||||
<MenuItems class="origin-top-right absolute right-0 mt-2 p-1 space-y-2 w-56 rounded-md shadow-lg bg-lime-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
|
<MenuItems class="origin-top-right absolute right-0 mt-2 p-1 space-y-2 w-56 rounded-md shadow-lg bg-lime-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
<div class="py-1">
|
<div class="py-1">
|
||||||
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes" :key="route.path" >
|
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes.filter( value => value.meta.index >= 0 )" :key="route.path" >
|
||||||
<a :href="route.path" target="_blank" rel="noopener noreferrer" :class="[active ? 'text-orange-300' : 'text-white', 'flex px-4 py-2 active:text-orange-500 rounded-lg h-fit align-middle transition-all ease-in-out duration-500']" v-if="route.path.startsWith('http')">
|
<a :href="route.path" target="_blank" rel="noopener noreferrer" :class="[active ? 'text-orange-300' : 'text-white', 'flex px-4 py-2 active:text-orange-500 rounded-lg h-fit align-middle transition-all ease-in-out duration-500']" v-if="route.path.startsWith('http')">
|
||||||
<div class="inline-flex px-3 py-1 space-x-1">
|
<div class="inline-flex px-3 py-1 space-x-1">
|
||||||
<span class="scale-75">
|
<span class="scale-75">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCounter, mdiEarth, mdiHandCoin, mdiHome, mdiInformation, mdiWeb } from '@mdi/js'
|
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCompare, mdiCounter, mdiEarth, mdiHandCoin, mdiHome, mdiInformation, mdiWeb } from '@mdi/js'
|
||||||
import About from '@/views/about/Index.vue'
|
import About from '@/views/about/Index.vue'
|
||||||
import AboutPage from '@/views/about/About.vue'
|
import AboutPage from '@/views/about/About.vue'
|
||||||
import Acknowledgements from '@/views/about/Acknowledgements.vue'
|
import Acknowledgements from '@/views/about/Acknowledgements.vue'
|
||||||
@ -13,8 +13,9 @@ import Refused from '@/views/errors/Refused.vue'
|
|||||||
import Results from '@/views/results/Index.vue'
|
import Results from '@/views/results/Index.vue'
|
||||||
import ResultsPage from '@/views/results/Results.vue'
|
import ResultsPage from '@/views/results/Results.vue'
|
||||||
import Scores from '@/views/results/Scores.vue'
|
import Scores from '@/views/results/Scores.vue'
|
||||||
import Answers from '@/views/results/Answers.vue'
|
import CompareAnswers from '@/views/results/CompareAnswers.vue'
|
||||||
import Statistics from '@/views/results/Statistics.vue'
|
import Statistics from '@/views/results/Statistics.vue'
|
||||||
|
import CompareResults from '@/views/results/CompareResults.vue'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -144,17 +145,28 @@ const routes = [
|
|||||||
component: Scores,
|
component: Scores,
|
||||||
meta: {
|
meta: {
|
||||||
index: 1,
|
index: 1,
|
||||||
title: 'All Scores',
|
title: 'Your Scores',
|
||||||
svgPath: mdiCounter,
|
svgPath: mdiCounter,
|
||||||
parentIndex: -1
|
parentIndex: -1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'compare',
|
||||||
|
name: 'CompareResults',
|
||||||
|
component: CompareResults,
|
||||||
|
meta: {
|
||||||
|
index: 2,
|
||||||
|
title: 'Compare Results',
|
||||||
|
svgPath: mdiCompare,
|
||||||
|
parentIndex: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'statistics',
|
path: 'statistics',
|
||||||
name: 'Statistics',
|
name: 'Statistics',
|
||||||
component: Statistics,
|
component: Statistics,
|
||||||
meta: {
|
meta: {
|
||||||
index: 2,
|
index: 3,
|
||||||
title: 'Statistics',
|
title: 'Statistics',
|
||||||
svgPath: mdiChartBox,
|
svgPath: mdiChartBox,
|
||||||
parentIndex: -1
|
parentIndex: -1
|
||||||
@ -163,10 +175,10 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: 'answers',
|
path: 'answers',
|
||||||
name: 'Answers',
|
name: 'Answers',
|
||||||
component: Answers,
|
component: CompareAnswers,
|
||||||
meta: {
|
meta: {
|
||||||
index: 3,
|
index: 4,
|
||||||
title: 'Global Answers',
|
title: 'Compare Answers',
|
||||||
svgPath: mdiEarth,
|
svgPath: mdiEarth,
|
||||||
parentIndex: -1
|
parentIndex: -1
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,19 @@ export const useAppStore = defineStore({
|
|||||||
id: 'app',
|
id: 'app',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
hasData: false,
|
hasData: false,
|
||||||
results: {}
|
answers: [],
|
||||||
|
playbooks: {},
|
||||||
|
results: {},
|
||||||
|
scores: {},
|
||||||
|
count: null
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
toggleData() {
|
toggleData() {
|
||||||
this.hasData = !this.hasData
|
this.hasData = !this.hasData
|
||||||
console.log('Toggled Has Data. New value', this.hasData)
|
console.log('Toggled Has Data. New value', this.hasData)
|
||||||
},
|
},
|
||||||
storeResults(results) {
|
store(key, data) {
|
||||||
this.results = JSON.parse(JSON.stringify(results))
|
this[key] = JSON.parse(JSON.stringify(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -93,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then( (response) => {
|
).then( (response) => {
|
||||||
this.appStore.storeResults(response.data)
|
this.appStore.store('results', response.data)
|
||||||
console.log('Results fetched from the server.')
|
console.log('Results fetched from the server.')
|
||||||
this.$router.push('/results')
|
this.$router.push('/results')
|
||||||
}).catch( (error) => {
|
}).catch( (error) => {
|
||||||
@ -125,7 +125,7 @@
|
|||||||
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex">
|
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex">
|
||||||
<input :type="this.questionStore.questions[this.id].select > 1 ? 'checkbox' : 'radio'" class="checkbox" :id="`q${this.id}-o${index}`" :value=index :key="`q${this.id}-o${index}`" v-model="answersStore.answers[this.id]" :disabled="this.questionStore.questions[this.id].select > 1 && this.answersStore.answers[this.id].length == this.questionStore.questions[this.id].select && !this.answersStore.answers[this.id].includes(index)">
|
<input :type="this.questionStore.questions[this.id].select > 1 ? 'checkbox' : 'radio'" class="checkbox" :id="`q${this.id}-o${index}`" :value=index :key="`q${this.id}-o${index}`" v-model="answersStore.answers[this.id]" :disabled="this.questionStore.questions[this.id].select > 1 && this.answersStore.answers[this.id].length == this.questionStore.questions[this.id].select && !this.answersStore.answers[this.id].includes(index)">
|
||||||
<label :for="`q${this.id}-o${index}`">
|
<label :for="`q${this.id}-o${index}`">
|
||||||
<div v-html="answer" class="uncial-antiqua w-full h-full p-2 transition-all duration-100 ease-in-out hover:bg-lime-200 hover:text-orange-600 hover:cursor-pointer" :aria-label="answer" :title="answer"></div>
|
<div v-html="answer" class="uncial-antiqua w-full h-full p-2 select-none transition-all duration-100 ease-in-out hover:bg-lime-200 hover:text-orange-600 hover:cursor-pointer" :aria-label="answer" :title="answer"></div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Global Answers
|
Compare Answers
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
|
|
101
client/src/views/results/CompareResults.vue
Normal file
101
client/src/views/results/CompareResults.vue
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
import Config from '@/config.js'
|
||||||
|
import Content from '@/components/Content.vue'
|
||||||
|
import Header from '@/components/Header.vue'
|
||||||
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
import ChevronDoubleRight from '@/components/icons/ChevronDoubleRight.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getResults()
|
||||||
|
},
|
||||||
|
name: 'CompareResults',
|
||||||
|
components: {
|
||||||
|
ChevronDoubleRight,
|
||||||
|
Content,
|
||||||
|
Header,
|
||||||
|
TextFrame
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getResults() {
|
||||||
|
axios.get(`${Config.SERVER}api/playbooks/`)
|
||||||
|
.then((response) => {
|
||||||
|
this.error = false
|
||||||
|
this.appStore.store('playbooks', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
axios.get(`${Config.SERVER}api/count/`)
|
||||||
|
.then((response) => {
|
||||||
|
this.error = false
|
||||||
|
this.appStore.store('count', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<TextFrame>
|
||||||
|
<Header>
|
||||||
|
Compare Results
|
||||||
|
</Header>
|
||||||
|
<Content>
|
||||||
|
<p class="text-leader">
|
||||||
|
Based on others who have taken this quiz, here are the playbooks of fellow travellers you are likely to meet along the way.
|
||||||
|
</p>
|
||||||
|
<table class="table-auto w-full max-w-sm mx-auto text-left">
|
||||||
|
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Playbook
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Number
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Percentage
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(number, playbook, index) in this.appStore.playbooks" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
|
||||||
|
<td v-if="this.appStore.results.playbooks.some(obj => obj.hasOwnProperty(playbook))">
|
||||||
|
<ChevronDoubleRight/>
|
||||||
|
</td>
|
||||||
|
<td v-else>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1 capitalize">
|
||||||
|
The {{ playbook }}
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1">
|
||||||
|
{{ number }}
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1">
|
||||||
|
{{ Math.round(100*number/this.appStore.count) }} %
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</Content>
|
||||||
|
</TextFrame>
|
||||||
|
</template>
|
@ -49,12 +49,11 @@
|
|||||||
<section v-for="playbook in this.appStore.results.playbooks" :key="Object.keys(playbook)[0]" class="border-solid border-b-2 border-lime-600 border-opacity-25">
|
<section v-for="playbook in this.appStore.results.playbooks" :key="Object.keys(playbook)[0]" class="border-solid border-b-2 border-lime-600 border-opacity-25">
|
||||||
<h2 class="flex justify-between">
|
<h2 class="flex justify-between">
|
||||||
<span class="uncial-antiqua align-bottom">
|
<span class="uncial-antiqua align-bottom">
|
||||||
<span class="text-xl">The</span> <span class="text-3xl">{{ Object.keys(playbook)[0].slice(0,1).toUpperCase()+Object.keys(playbook)[0].slice(1) }}</span>
|
<span class="text-xl">The</span> <span class="text-3xl capitalize">{{ Object.keys(playbook)[0] }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm">Pages {{ Object.values(playbook)[0].pages }}</span>
|
<span class="text-sm">Pages {{ Object.values(playbook)[0].pages }}</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-leader">
|
<p class="text-leader" v-html="Object.values(playbook)[0].flavour">
|
||||||
{{ Object.values(playbook)[0].flavour }}
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{{ Object.values(playbook)[0].blurb }}
|
{{ Object.values(playbook)[0].blurb }}
|
||||||
|
@ -23,16 +23,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Scores
|
Your Scores
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
<p>
|
<p class="text-leader">
|
||||||
The following are your scores for each playbook:
|
While the playbook you are is the one most reflected by your answers, here are the other playbooks and the extent to which they have a bearing upon your journey.
|
||||||
</p>
|
</p>
|
||||||
<table class="table-auto w-full max-w-xs mx-auto">
|
<table class="table-auto w-full max-w-sm mx-auto text-left">
|
||||||
<thead>
|
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th class="pl-10">
|
||||||
Playbook
|
Playbook
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
@ -41,11 +41,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(score, playbook) in this.appStore.results.all_playbooks" :key="playbook">
|
<tr v-for="(score, playbook, index) in this.appStore.results.all_playbooks" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
|
||||||
<td>
|
<td scope="col" class="py-1 pl-10 capitalize">
|
||||||
The {{ playbook.slice(0,1).toUpperCase() + playbook.slice(1) }}
|
The {{ playbook }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td scope="col" class="py-1">
|
||||||
{{ Math.round(100*score/this.appStore.results.max_score) }} %
|
{{ Math.round(100*score/this.appStore.results.max_score) }} %
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,13 +1,49 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
import Config from '@/config.js'
|
||||||
import Content from '@/components/Content.vue'
|
import Content from '@/components/Content.vue'
|
||||||
import Header from '@/components/Header.vue'
|
import Header from '@/components/Header.vue'
|
||||||
import TextFrame from '@/components/TextFrame.vue'
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
import ChevronDoubleRight from '@/components/icons/ChevronDoubleRight.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getScores()
|
||||||
|
},
|
||||||
name: 'Statistics',
|
name: 'Statistics',
|
||||||
components: {
|
components: {
|
||||||
|
ChevronDoubleRight,
|
||||||
Content,
|
Content,
|
||||||
Header,
|
Header,
|
||||||
TextFrame
|
TextFrame
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getScores() {
|
||||||
|
axios.get(`${Config.SERVER}api/scores/`)
|
||||||
|
.then((response) => {
|
||||||
|
this.error = false
|
||||||
|
this.appStore.store('scores', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
axios.get(`${Config.SERVER}api/count/`)
|
||||||
|
.then((response) => {
|
||||||
|
this.error = false
|
||||||
|
this.appStore.store('count', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -17,7 +53,62 @@
|
|||||||
Statistics
|
Statistics
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
|
<p class="text-leader">
|
||||||
|
Sometimes, it can help to have some additional insight into the likelihood of meeting different people.
|
||||||
|
Or, indeed, it can provide insight into how the questions we ask of each other bias the way we perceive the world.
|
||||||
|
</p>
|
||||||
|
<table class="table-auto w-full max-w-lg mx-auto text-left">
|
||||||
|
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Playbook
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Your Score
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Mean Score
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Median Score
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Standard Deviation
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(stats, playbook, index) in this.appStore.scores" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
|
||||||
|
<td v-if="this.appStore.results.playbooks.some(obj => obj.hasOwnProperty(playbook))">
|
||||||
|
<ChevronDoubleRight/>
|
||||||
|
</td>
|
||||||
|
<td v-else>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1 capitalize">
|
||||||
|
The {{ playbook }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ Math.round(100*this.appStore.results.all_playbooks[playbook]/this.appStore.results.max_score) }}
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1">
|
||||||
|
{{ Math.round(stats.mean * 100) / 100 }}
|
||||||
|
</td>
|
||||||
|
<td scope="col" class="py-1">
|
||||||
|
{{ Math.round(stats.median * 100) / 100 }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ Math.round(stats.standard_deviation * 100) / 100 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</template>
|
</template>
|
Loading…
Reference in New Issue
Block a user