201201
202202 <!-- Responses view for individual responses -->
203203 <section v-else >
204+ <div class =" pagination-block" :class =" { 'large-width': isMobile }" >
205+ <div class =" pagination-items" >
206+ <NcButton
207+ type =" tertiary"
208+ :disabled =" totalPages === 1 || pageNumber <= 1"
209+ :aria-label =" t('tables', 'Go to first page')"
210+ @click =" pageNumber = 1" >
211+ <template #icon >
212+ <PageFirstIcon :size =" 20" />
213+ </template >
214+ </NcButton >
215+ <NcButton
216+ type =" tertiary"
217+ :disabled =" totalPages === 1 || pageNumber <= 1"
218+ :aria-label =" t('tables', 'Go to previous page')"
219+ @click =" pageNumber--" >
220+ <template #icon >
221+ <IconChevronLeft :size =" 20" />
222+ </template >
223+ </NcButton >
224+ <div class =" page-number" >
225+ <NcSelect
226+ v-model =" pageNumber"
227+ :options =" allPageNumbersArray"
228+ :aria-label-combobox =" t('tables', 'Page number')" >
229+ <template #selected-option-container =" { option } " >
230+ <span class =" selected-page" >
231+ {{ option.label }} of {{ totalPages }}
232+ </span >
233+ </template >
234+ </NcSelect >
235+ </div >
236+ <NcButton
237+ type =" tertiary"
238+ :disabled =" totalPages === 1 || pageNumber >= totalPages"
239+ :aria-label =" t('tables', 'Go to next page')"
240+ @click =" pageNumber++" >
241+ <template #icon >
242+ <IconChevronRight :size =" 20" />
243+ </template >
244+ </NcButton >
245+ <NcButton
246+ type =" tertiary"
247+ :disabled =" totalPages === 1 || pageNumber >= totalPages"
248+ :aria-label =" t('tables', 'Go to last page')"
249+ @click =" pageNumber = totalPages" >
250+ <template #icon >
251+ <PageLastIcon :size =" 20" />
252+ </template >
253+ </NcButton >
254+
255+ <div >
256+ <NcTextField
257+ v-model =" submissionSearch"
258+ :label =" t('forms', 'Search')"
259+ trailing-button-icon =" close"
260+ :show-trailing-button =" submissionSearch.length > 0"
261+ @trailing-button-click =" submissionSearch = ''" >
262+ <template #icon >
263+ <IconMagnify :size =" 20" />
264+ </template >
265+ </NcTextField >
266+ </div >
267+ </div >
268+ </div >
269+
204270 <Submission
205- v-for =" submission in submissions "
271+ v-for =" submission in currentPageSubmissions "
206272 :key =" submission.id"
207273 :submission =" submission"
208274 :questions =" questions"
209275 :can-delete-submission =" canDeleteSubmissions"
276+ :highlight =" submissionSearch"
210277 @delete =" deleteSubmission(submission.id)" />
211278 </section >
212279 </template >
@@ -239,6 +306,7 @@ import NcActionSeparator from '@nextcloud/vue/components/NcActionSeparator'
239306import NcAppContent from ' @nextcloud/vue/components/NcAppContent'
240307import NcButton from ' @nextcloud/vue/components/NcButton'
241308import NcDialog from ' @nextcloud/vue/components/NcDialog'
309+ import NcTextField from ' @nextcloud/vue/components/NcTextField'
242310import NcEmptyContent from ' @nextcloud/vue/components/NcEmptyContent'
243311import NcLoadingIcon from ' @nextcloud/vue/components/NcLoadingIcon'
244312import axios from ' @nextcloud/axios'
@@ -263,6 +331,11 @@ import IconRefresh from 'vue-material-design-icons/Refresh.vue'
263331import IconShareVariant from ' vue-material-design-icons/ShareVariant.vue'
264332import IconTable from ' vue-material-design-icons/Table.vue'
265333import IconTableSvg from ' @mdi/svg/svg/table.svg?raw'
334+ import NcSelect from ' @nextcloud/vue/components/NcSelect'
335+ import PageLastIcon from ' vue-material-design-icons/PageLast.vue'
336+ import PageFirstIcon from ' vue-material-design-icons/PageFirst.vue'
337+ import IconChevronRight from ' vue-material-design-icons/ChevronRight.vue'
338+ import IconMagnify from ' vue-material-design-icons/Magnify.vue'
266339
267340import { FormState } from ' ../models/FormStates.ts'
268341import ResultsSummary from ' ../components/Results/ResultsSummary.vue'
@@ -316,6 +389,12 @@ export default {
316389 NcAppContent,
317390 NcButton,
318391 NcDialog,
392+ NcTextField,
393+ NcSelect,
394+ PageLastIcon,
395+ PageFirstIcon,
396+ IconChevronRight,
397+ IconMagnify,
319398 NcEmptyContent,
320399 NcLoadingIcon,
321400 PillMenu,
@@ -348,6 +427,10 @@ export default {
348427 picker: null ,
349428 showConfirmDeleteDialog: false ,
350429
430+ submissionSearch: ' ' ,
431+ pageNumber: 1 ,
432+ rowsPerPage: 50 ,
433+
351434 linkedFileNotAvailableButtons: [
352435 {
353436 label: t (' forms' , ' Unlink spreadsheet' ),
@@ -428,6 +511,34 @@ export default {
428511 }
429512 return this .canEditForm && this .form .fileId && ! this .form .filePath
430513 },
514+
515+ allPageNumbersArray () {
516+ return Array .from (
517+ { length: this .totalPages },
518+ (value , index ) => 1 + index,
519+ )
520+ },
521+ currentPageSubmissions () {
522+ return this .getFilteredSubmissions .slice (
523+ (this .pageNumber - 1 ) * this .rowsPerPage ,
524+ (this .pageNumber - 1 ) * this .rowsPerPage + this .rowsPerPage ,
525+ )
526+ },
527+ totalPages () {
528+ return Math .ceil (this .getFilteredSubmissions .length / this .rowsPerPage )
529+ },
530+ getFilteredSubmissions () {
531+ if (! this .submissionSearch ) {
532+ return this .submissions
533+ }
534+
535+ const submissionFilter = (submission ) =>
536+ submission .answers .filter ((answer ) =>
537+ answer .text .includes (this .submissionSearch ),
538+ ).length > 0
539+
540+ return this .submissions .filter (submissionFilter)
541+ },
431542 },
432543
433544 watch: {
@@ -836,4 +947,51 @@ export default {
836947 }
837948 }
838949}
950+
951+ : deep (.vs__clear ) {
952+ display: none;
953+ }
954+
955+ : deep (.v - select ) {
956+ min- width: 95px ! important;
957+ .vs__dropdown - toggle {
958+ background: none;
959+ }
960+ }
961+
962+ .selected - page {
963+ padding- left: 5px ;
964+
965+ display: inline- flex;
966+ align- items: center;
967+ }
968+
969+ .page - number {
970+ padding- inline: 5px ;
971+ }
972+
973+ .large - width {
974+ width: 100vw ! important;
975+ left: 0 ! important;
976+ }
977+
978+ .pagination - items {
979+ background- color: var (-- color- main- background);
980+ border- radius: var (-- border- radius- large);
981+ pointer- events: all;
982+
983+ display: flex;
984+ align- items: center;
985+ }
986+
987+ .pagination - block {
988+ box- shadow: var (-- box- shadow);
989+ filter: drop- shadow (0 1px 6px var (-- color- box- shadow));
990+ width: 100 % ;
991+ pointer- events: none;
992+
993+ display: flex;
994+ justify- content: center;
995+ align- items: center;
996+ }
839997< / style>
0 commit comments