form listing new design + delete form modal (#30)

Co-authored-by: JhumanJ <julien@nahum.net>
This commit is contained in:
Chirag 2022-11-16 17:25:50 +05:30 committed by GitHub
parent b9ba6e1e29
commit d8bf96501b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 136 additions and 60 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -31,7 +31,7 @@ export default {
}, },
props: { props: {
dropdownClass: { type: String, default: 'origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 z-50' } dropdownClass: { type: String, default: 'origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 z-20' }
}, },
data () { data () {
return { return {

View File

@ -5,7 +5,7 @@
</div> </div>
<dropdown v-else class="inline" dusk="nav-dropdown"> <dropdown v-else class="inline" dusk="nav-dropdown">
<template #trigger="{toggle}"> <template #trigger="{toggle}">
<v-button color="light-gray" class="mr-2" @click="toggle"> <v-button color="white" class="mr-2" @click="toggle">
<svg class="w-4 h-4 inline -mt-1" viewBox="0 0 16 4" fill="none" <svg class="w-4 h-4 inline -mt-1" viewBox="0 0 16 4" fill="none"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<path <path
@ -34,6 +34,26 @@
</svg> </svg>
View form View form
</router-link> </router-link>
<router-link v-if="isMainPage" :to="{name:'forms.edit', params: {slug: form.slug}}"
class="block block px-4 py-2 text-md text-gray-700 dark:text-white hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center"
v-track.edit_form_click="{form_id:form.id, form_slug:form.slug}"
>
<svg class="w-4 h-4 mr-2" width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M8.99998 15.6662H16.5M1.5 15.6662H2.89545C3.3031 15.6662 3.50693 15.6662 3.69874 15.6202C3.8688 15.5793 4.03138 15.512 4.1805 15.4206C4.34869 15.3175 4.49282 15.1734 4.78107 14.8852L15.25 4.4162C15.9404 3.72585 15.9404 2.60656 15.25 1.9162C14.5597 1.22585 13.4404 1.22585 12.75 1.9162L2.28105 12.3852C1.9928 12.6734 1.84867 12.8175 1.7456 12.9857C1.65422 13.1348 1.58688 13.2974 1.54605 13.4675C1.5 13.6593 1.5 13.8631 1.5 14.2708V15.6662Z"
stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Edit
</router-link>
<a href="#" v-if="isMainPage"
class="block block px-4 py-2 text-md text-gray-700 dark:text-white hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center"
@click.prevent="copyLink"
>
<svg class="w-4 h-4 mr-2" viewBox="0 0 16 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.00016 8.33317H4.66683C2.82588 8.33317 1.3335 6.84079 1.3335 4.99984C1.3335 3.15889 2.82588 1.6665 4.66683 1.6665H6.00016M10.0002 8.33317H11.3335C13.1744 8.33317 14.6668 6.84079 14.6668 4.99984C14.6668 3.15889 13.1744 1.6665 11.3335 1.6665H10.0002M4.66683 4.99984L11.3335 4.99984" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Copy link to share
</a>
<a href="#" <a href="#"
class="block block px-4 py-2 text-md text-gray-700 dark:text-white hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center" class="block block px-4 py-2 text-md text-gray-700 dark:text-white hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center"
v-track.duplicate_form_click="{form_id:form.id, form_slug:form.slug}" v-track.duplicate_form_click="{form_id:form.id, form_slug:form.slug}"
@ -61,7 +81,7 @@
<a href="#" <a href="#"
class="block block px-4 py-2 text-md text-red-600 hover:bg-red-50 flex items-center" class="block block px-4 py-2 text-md text-red-600 hover:bg-red-50 flex items-center"
v-track.delete_form_click="{form_id:form.id, form_slug:form.slug}" v-track.delete_form_click="{form_id:form.id, form_slug:form.slug}"
@click.prevent="alertConfirm('Do you really want to delete this form?',deleteForm)" @click.prevent="showDeleteFormModal=true"
> >
<svg class="w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" <svg class="w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"> stroke="currentColor">
@ -73,6 +93,30 @@
</a> </a>
</dropdown> </dropdown>
<!-- Delete Form Modal -->
<modal :show="showDeleteFormModal" icon-color="red" @close="showDeleteFormModal=false" max-width="sm">
<template #icon>
<svg class="w-10 h-10" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
</template>
<template #title>
Delete form
</template>
<div class="p-3">
<p>
If you want to permanently delete this form and all of its data, you can do so below.
</p>
<div class="flex mt-4">
<v-button class="sm:w-1/2 mr-4" color="white" @click.prevent="showDeleteFormModal=false">Cancel</v-button>
<v-button class="sm:w-1/2" color="red" :loading="loadingDelete" @click.prevent="deleteForm">Yes, delete it</v-button>
</div>
</div>
</modal>
<create-template-modal :form="form" :show="showCreateTemplateModal" @close="showCreateTemplateModal=false"/> <create-template-modal :form="form" :show="showCreateTemplateModal" @close="showCreateTemplateModal=false"/>
</div> </div>
</template> </template>
@ -87,12 +131,14 @@ export default {
name: 'ExtraMenu', name: 'ExtraMenu',
components: { Dropdown, CreateTemplateModal }, components: { Dropdown, CreateTemplateModal },
props: { props: {
form: { type: Object, required: true } form: { type: Object, required: true },
isMainPage: { type: Boolean, required: false, default: false }
}, },
data: () => ({ data: () => ({
loadingDuplicate: false, loadingDuplicate: false,
loadingDelete: false, loadingDelete: false,
showDeleteFormModal: false,
showCreateTemplateModal: false showCreateTemplateModal: false
}), }),
@ -104,6 +150,14 @@ export default {
}, },
methods: { methods: {
copyLink(){
const el = document.createElement('textarea')
el.value = this.form.share_url
document.body.appendChild(el)
el.select()
document.execCommand('copy')
document.body.removeChild(el)
},
duplicateForm() { duplicateForm() {
if (this.loadingDuplicate) return if (this.loadingDuplicate) return
this.loadingDuplicate = true this.loadingDuplicate = true

View File

@ -1,21 +1,27 @@
<template> <template>
<div class="flex flex-col min-h-full mt-6"> <div class="bg-white">
<div class="w-full flex-grow md:w-3/5 lg:w-1/2 md:mx-auto md:max-w-2xl px-4"> <div class="flex bg-gray-50 pb-5">
<div> <div class="w-full md:w-4/5 lg:w-3/5 md:mx-auto md:max-w-4xl p-4">
<div class="flex flex-wrap items-center mt-6 mb-4"> <div class="pt-4 pb-0">
<h2 class="text-nt-blue text-3xl font-bold flex-grow"> <div class="flex">
<h2 class="flex-grow text-gray-900">
Your Forms Your Forms
</h2> </h2>
<v-button v-track.create_form_click class="mt-4 sm:mt-0" :to="{name:'forms.create'}" @click="showCreateFormModal=true"> <v-button v-track.create_form_click :to="{name:'forms.create'}">
<svg class="w-4 h-4 text-white inline mr-1 -mt-1" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.99996 1.1665V12.8332M1.16663 6.99984H12.8333" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Create a new form Create a new form
</v-button> </v-button>
</div> </div>
<small class="flex text-gray-500">Manage your forms and submissions.</small>
<p v-if="!formsLoading && enrichedForms.length === 0 && !isFilteringForms"> </div>
You don't have any form yet. </div>
</p> </div>
<div v-else-if="forms.length > 0" class="mb-10"> <div class="flex bg-white">
<text-input v-if="forms.length > 5" class="mb-6" :form="searchForm" name="search" label="Search a form" <div class="w-full md:w-4/5 lg:w-3/5 md:mx-auto md:max-w-4xl px-4">
<div class="mt-8 pb-0">
<text-input v-if="forms.length > 0" class="mb-6" :form="searchForm" name="search" label="Search a form"
placeholder="Name of form to search" placeholder="Name of form to search"
/> />
<div v-if="allTags.length > 0" class="mb-6"> <div v-if="allTags.length > 0" class="mb-6">
@ -27,18 +33,36 @@
{{ tag }} {{ tag }}
</div> </div>
</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-if="!formsLoading && enrichedForms.length === 0" class="flex flex-wrap justify-center max-w-4xl">
<div v-for="(form, index) in enrichedForms" :key="form.id" <img loading="lazy" class="w-56"
class="p-4 w-full mx-auto border-gray-300 hover:bg-blue-100 dark:hover:bg-blue-900 transition-colors cursor-pointer relative" :src="asset('img/pages/forms/search_notfound.png')" alt="search-not-found">
:class="{'border-t':index!==0, 'bg-gray-50 dark:bg-gray-400':form.visibility=='draft'}" <h3 class="w-full mt-4 text-center text-gray-900 font-semibold">No forms found</h3>
<div v-if="isFilteringForms && enrichedForms.length === 0 && searchForm.search" class="mt-2 w-full text-center">
Your search "{{searchForm.search}}" did not match any forms. Please try again.
</div>
<v-button v-if="forms.length === 0" class="mt-4" v-track.create_form_click :to="{name:'forms.create'}">
<svg class="w-4 h-4 text-white inline mr-1 -mt-1" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.99996 1.1665V12.8332M1.16663 6.99984H12.8333" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Create a new form
</v-button>
</div>
<div v-else-if="forms.length > 0" class="mb-10">
<div v-if="enrichedForms && enrichedForms.length">
<div v-for="(form) in enrichedForms" :key="form.id"
class="mt-4 p-4 flex group bg-white hover:bg-gray-50 dark:bg-notion-dark items-center"
> >
<div class="items-center space-x-4 truncate"> <div class="flex-grow items-center truncate cursor-pointer" role="button" @click.prevent="viewForm(form)">
<p class="truncate float-left"> <span class="font-semibold text-gray-900 dark:text-white">{{ form.title }}</span>
{{ form.title }} <span v-if="form.submissions_count" class="text-gray-400 ml-1">- {{ <ul class="flex text-gray-500">
form.submissions_count <li class="pr-1">{{ form.views_count }} view{{ form.views_count > 0 ? 's' : '' }}</li>
}} Submission{{ form.submissions_count > 0 ? 's' : '' }}</span> <li class="list-disc ml-6 pr-1">{{ form.submissions_count }}
</p> submission{{ form.submissions_count > 0 ? 's' : '' }}
<div v-if="form.tags && form.tags.length > 0" class="float-right hidden sm:block"> </li>
<li class="list-disc ml-6 pr-1 text-blue-500" v-if="form.visibility=='draft'">Draft (not public)</li>
<li class="list-disc ml-6">Edited {{ form.last_edited_human }}</li>
</ul>
<div v-if="form.tags && form.tags.length > 0" class="mt-1">
<template v-for="(tag,i) in form.tags"> <template v-for="(tag,i) in form.tags">
<div v-if="i<1" :key="tag" <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" class="bg-gray-300 dark:bg-gray-700 text-white px-2 py-1 mr-2 text-xs inline rounded-lg font-semibold"
@ -53,22 +77,16 @@
</template> </template>
</div> </div>
</div> </div>
<router-link class="absolute inset-0" <extra-menu :form="form" :isMainPage="true" />
:to="{params:{slug:form.slug},name:'forms.show'}"
/>
</div> </div>
</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 v-if="formsLoading" class="text-center"> <div v-if="formsLoading" class="text-center">
<loader class="h-6 w-6 text-nt-blue mx-auto" /> <loader class="h-6 w-6 text-nt-blue mx-auto" />
</div> </div>
</div> </div>
</div> </div>
</div>
<open-form-footer class="mt-8 border-t" /> <open-form-footer class="mt-8 border-t" />
</div> </div>
</template> </template>
@ -80,6 +98,7 @@ import Fuse from 'fuse.js'
import Form from 'vform' import Form from 'vform'
import TextInput from '../components/forms/TextInput' import TextInput from '../components/forms/TextInput'
import OpenFormFooter from '../components/pages/OpenFormFooter' import OpenFormFooter from '../components/pages/OpenFormFooter'
import ExtraMenu from '../components/pages/forms/show/ExtraMenu'
const loadForms = function () { const loadForms = function () {
store.commit('open/forms/startLoading') store.commit('open/forms/startLoading')
@ -89,7 +108,7 @@ const loadForms = function () {
} }
export default { export default {
components: { OpenFormFooter, TextInput }, components: { OpenFormFooter, TextInput, ExtraMenu },
beforeRouteEnter (to, from, next) { beforeRouteEnter (to, from, next) {
loadForms() loadForms()
@ -127,6 +146,9 @@ export default {
} else { } else {
this.selectedTags.splice(idx, 1) this.selectedTags.splice(idx, 1)
} }
},
viewForm (form) {
this.$router.push({name: 'forms.show', params: {slug: form.slug}})
} }
}, },