179 lines
6.2 KiB
Vue
179 lines
6.2 KiB
Vue
<template>
|
|
<div class="flex flex-col min-h-full mt-6">
|
|
<div class="w-full flex-grow md:w-3/5 lg:w-1/2 md:mx-auto md:max-w-2xl px-4">
|
|
<div>
|
|
<div class="flex flex-wrap items-center mt-6 mb-4">
|
|
<h2 class="text-nt-blue text-3xl font-bold flex-grow">
|
|
Your Forms
|
|
</h2>
|
|
<fancy-link v-track.create_form_click class="mt-4 sm:mt-0" :to="{name:'forms.create'}" color="nt-blue" @click="showCreateFormModal=true">
|
|
Create a new form
|
|
</fancy-link>
|
|
</div>
|
|
<div v-if="formsLoading" class="text-center">
|
|
<loader class="h-6 w-6 text-nt-blue mx-auto" />
|
|
</div>
|
|
<p v-else-if="enrichedForms.length === 0 && !isFilteringForms">
|
|
You don't have any form yet.
|
|
</p>
|
|
<div v-else class="mb-10">
|
|
<text-input v-if="forms.length > 5" class="mb-6" :form="searchForm" name="search" label="Search a form"
|
|
placeholder="Name of form to search"
|
|
/>
|
|
<div v-if="allTags.length > 0" class="mb-6">
|
|
<div v-for="tag in allTags" :key="tag"
|
|
:class="['text-white p-2 text-xs inline rounded-lg font-semibold cursor-pointer mr-2',{'bg-gray-500 dark:bg-gray-400':selectedTags.includes(tag), 'bg-gray-300 dark:bg-gray-700':!selectedTags.includes(tag)}]"
|
|
title="Click for filter by tag(s)"
|
|
@click="onTagClick(tag)"
|
|
>
|
|
{{ tag }}
|
|
</div>
|
|
</div>
|
|
<div v-if="enrichedForms && enrichedForms.length" class="border border border-gray-300 dark:bg-notion-dark-light rounded-md w-full">
|
|
<div v-for="(form, index) in enrichedForms" :key="form.id"
|
|
class="p-4 w-full mx-auto border-gray-300 hover:bg-blue-100 dark:hover:bg-blue-900 transition-colors cursor-pointer relative"
|
|
:class="{'border-t':index!==0, 'bg-gray-50 dark:bg-gray-400':form.visibility=='draft'}"
|
|
>
|
|
<div class="items-center space-x-4 truncate">
|
|
<p class="truncate float-left">
|
|
{{ form.title }} <span v-if="form.submissions_count" class="text-gray-400 ml-1">- {{
|
|
form.submissions_count
|
|
}} Submission{{ form.submissions_count > 0 ? 's' : '' }}</span>
|
|
</p>
|
|
<div v-if="form.tags && form.tags.length > 0" class="float-right hidden sm:block">
|
|
<template v-for="(tag,i) in form.tags">
|
|
<div v-if="i<1" :key="tag"
|
|
class="bg-gray-300 dark:bg-gray-700 text-white px-2 py-1 mr-2 text-xs inline rounded-lg font-semibold"
|
|
>
|
|
{{ tag }}
|
|
</div>
|
|
<div v-if="i==1" :key="tag"
|
|
class="bg-gray-300 dark:bg-gray-700 text-white px-2 py-1 mr-2 text-xs inline rounded-lg font-semibold"
|
|
>
|
|
{{ form.tags.length-1 }} more
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<router-link class="absolute inset-0"
|
|
:to="{params:{slug:form.slug},name:'forms.show'}"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<p class="text-gray-400 dark:text-gray-600 mt-2 px-4">
|
|
You have {{ forms.length }} forms<template v-if="isFilteringForms">
|
|
({{ enrichedForms.length }} matching search criteria)
|
|
</template>.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<open-form-footer class="mt-8 border-t" />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import store from '~/store'
|
|
import { mapGetters, mapState } from 'vuex'
|
|
import Fuse from 'fuse.js'
|
|
import Form from 'vform'
|
|
import TextInput from '../components/forms/TextInput'
|
|
import OpenFormFooter from '../components/pages/OpenFormFooter'
|
|
|
|
const loadForms = function () {
|
|
store.commit('open/forms/startLoading')
|
|
store.dispatch('open/workspaces/loadIfEmpty').then(() => {
|
|
store.dispatch('open/forms/load', store.state['open/workspaces'].currentId)
|
|
})
|
|
}
|
|
|
|
export default {
|
|
components: { OpenFormFooter, TextInput },
|
|
|
|
beforeRouteEnter (to, from, next) {
|
|
loadForms()
|
|
next()
|
|
},
|
|
middleware: 'auth',
|
|
|
|
props: {
|
|
metaTitle: { type: String, default: 'Your Forms' },
|
|
metaDescription: { type: String, default: 'All of your OpnForm are here. Create new forms, or update your existing one!' }
|
|
},
|
|
|
|
data () {
|
|
return {
|
|
showEditFormModal: false,
|
|
selectedForm: null,
|
|
searchForm: new Form({
|
|
search: ''
|
|
}),
|
|
selectedTags: []
|
|
}
|
|
},
|
|
|
|
mounted () {},
|
|
|
|
methods: {
|
|
editForm (form) {
|
|
this.selectedForm = form
|
|
this.showEditFormModal = true
|
|
},
|
|
onTagClick (tag) {
|
|
const idx = this.selectedTags.indexOf(tag)
|
|
if (idx === -1) {
|
|
this.selectedTags.push(tag)
|
|
} else {
|
|
this.selectedTags.splice(idx, 1)
|
|
}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
...mapGetters({
|
|
user: 'auth/user'
|
|
}),
|
|
...mapState({
|
|
forms: state => state['open/forms'].content,
|
|
formsLoading: state => state['open/forms'].loading
|
|
}),
|
|
isFilteringForms () {
|
|
return (this.searchForm.search !== '' && this.searchForm.search !== null) || this.selectedTags.length > 0
|
|
},
|
|
enrichedForms () {
|
|
let enrichedForms = this.forms.map((form) => {
|
|
form.workspace = this.$store.getters['open/workspaces/getById'](form.workspace_id)
|
|
return form
|
|
})
|
|
|
|
// Filter by Selected Tags
|
|
if (this.selectedTags.length > 0) {
|
|
enrichedForms = enrichedForms.filter((item) => {
|
|
return (item.tags && item.tags.length > 0) ? this.selectedTags.every(r => item.tags.includes(r)) : false
|
|
})
|
|
}
|
|
|
|
if (!this.isFilteringForms || this.searchForm.search === '' || this.searchForm.search === null) {
|
|
return enrichedForms
|
|
}
|
|
|
|
// Fuze search
|
|
const fuzeOptions = {
|
|
keys: [
|
|
'title',
|
|
'slug',
|
|
'tags'
|
|
]
|
|
}
|
|
const fuse = new Fuse(enrichedForms, fuzeOptions)
|
|
return fuse.search(this.searchForm.search).map((res) => {
|
|
return res.item
|
|
})
|
|
},
|
|
allTags () {
|
|
return this.$store.getters['open/forms/getAllTags']
|
|
}
|
|
}
|
|
}
|
|
</script>
|