From 8e47b49e9a18eb99f8c10607579dad6c87eba19c Mon Sep 17 00:00:00 2001
From: Chirag Chhatrala <60499540+chiragchhatrala@users.noreply.github.com>
Date: Fri, 8 Sep 2023 16:30:28 +0530
Subject: [PATCH] Improve Templates (#183)
* Improve Templates
* Fix test case
* Update AI GenerateTemplate
* update openai client and GPT completer
* composer.lock
* Update types and list json with script
* Template changes
* fix on draft template
* Finish opnform templates
---------
Co-authored-by: Forms Dev
+ {{ template.name }} +
++ {{ cleanQuotes(template.short_description) }} +
+Discover our beautiful templates
+If you need inspiration, checkout our templates.
+- Template does not exist. -
-+ We could not find this template. +
+ ++ {{ cleanQuotes(template.short_description) }} +
++ Template Preview +
++ Everything you need to know about this template. +
+
+
+ You can directly share your form link, or embed the form on your website. It's magic! 🪄 +
++ Our collection of beautiful templates to create your own forms! +
- No any templates found. -
-- {{ formatCreatedDate(template.created_at) }}
-{{ template.name }}
-+ No templates found. +
+Generous, unlimited free plan.
@@ -123,10 +125,11 @@ import MoreFeatures from '~/components/pages/welcome/MoreFeatures.vue' import AiFeature from '~/components/pages/welcome/AiFeature.vue' import OpenFormFooter from '../components/pages/OpenFormFooter.vue' import Testimonials from '../components/pages/welcome/Testimonials.vue' +import TemplatesSlider from '../components/pages/welcome/TemplatesSlider.vue' import SeoMeta from '../mixins/seo-meta.js' export default { - components: {Testimonials, OpenFormFooter, Features, MoreFeatures, AiFeature}, + components: {Testimonials, OpenFormFooter, Features, MoreFeatures, AiFeature, TemplatesSlider}, layout: 'default', diff --git a/resources/js/router/routes.js b/resources/js/router/routes.js index d31da75..fa7f2ce 100644 --- a/resources/js/router/routes.js +++ b/resources/js/router/routes.js @@ -67,8 +67,8 @@ export default [ { path: '/forms/:slug', name: 'forms.show_public', component: page('forms/show-public.vue') }, // Templates - { path: '/templates', name: 'templates', component: page('templates/templates.vue') }, - { path: '/templates/:slug', name: 'templates.show', component: page('templates/show.vue') }, + { path: '/form-templates', name: 'templates', component: page('templates/templates.vue') }, + { path: '/form-templates/:slug', name: 'templates.show', component: page('templates/show.vue') }, { path: '*', component: page('errors/404.vue') } ] diff --git a/resources/js/store/modules/open/templates.js b/resources/js/store/modules/open/templates.js index a03936f..3e229fa 100644 --- a/resources/js/store/modules/open/templates.js +++ b/resources/js/store/modules/open/templates.js @@ -1,55 +1,124 @@ -import Vue from 'vue' import axios from 'axios' +export const templatesEndpoint = '/api/templates' +export const namespaced = true + // state export const state = { content: [], + industries: {}, + types: {}, + allLoaded: false, loading: false } // getters export const getters = { - getById: (state) => (id) => { - if (state.content.length === 0) return null - return state.content.find(item => item.id === id) - }, getBySlug: (state) => (slug) => { if (state.content.length === 0) return null return state.content.find(item => item.slug === slug) }, + getTemplateTypes: (state) => (slugs) => { + if (state.types.length === 0) return null + return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name }) + }, + getTemplateIndustries: (state) => (slugs) => { + if (state.industries.length === 0) return null + return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name }) + } } // mutations export const mutations = { set (state, items) { state.content = items + state.allLoaded = true + }, + append (state, items) { + const ids = items.map((item) => { return item.id }) + state.content = state.content.filter((val) => !ids.includes(val.id)) + state.content = state.content.concat(items) }, addOrUpdate (state, item) { state.content = state.content.filter((val) => val.id !== item.id) state.content.push(item) }, - startLoading () { + remove (state, item) { + state.content = state.content.filter((val) => val.id !== item.id) + }, + startLoading (state) { state.loading = true }, - stopLoading () { + stopLoading (state) { state.loading = false + }, + setAllLoaded (state, val) { + state.allLoaded = val } } // actions export const actions = { - load (context) { + resetState (context) { context.commit('set', []) + context.commit('stopLoading') + }, + loadTypesAndIndustries (context) { + if (Object.keys(context.state.industries).length === 0) { + import('@/data/forms/templates/industries.json').then((module) => { + context.state.industries = module.default + }) + } + if (Object.keys(context.state.types).length === 0) { + import('@/data/forms/templates/types.json').then((module) => { + context.state.types = module.default + }) + } + }, + loadTemplate (context, slug) { context.commit('startLoading') - return axios.get('/api/templates').then((response) => { - context.commit('set', response.data) + context.dispatch('loadTypesAndIndustries') + + if (context.getters.getBySlug(slug)) { + context.commit('stopLoading') + return Promise.resolve() + } + + return axios.get(templatesEndpoint + '/' + slug).then((response) => { + context.commit('addOrUpdate', response.data) + context.commit('stopLoading') + }).catch((error) => { context.commit('stopLoading') }) }, - loadIfEmpty ({ context, dispatch, state }) { - if (state.content.length === 0) { - return dispatch('load') + loadAll (context) { + context.commit('startLoading') + context.dispatch('loadTypesAndIndustries') + return axios.get(templatesEndpoint).then((response) => { + context.commit('append', response.data) + context.commit('setAllLoaded', true) + context.commit('stopLoading') + }).catch((error) => { + context.commit('stopLoading') + }) + }, + loadIfEmpty (context) { + if (!context.state.allLoaded) { + return context.dispatch('loadAll') } + context.commit('stopLoading') return Promise.resolve() }, + loadWithLimit (context, limit) { + context.commit('startLoading') + context.dispatch('loadTypesAndIndustries') + + return axios.get(templatesEndpoint + '?limit=' + limit).then((response) => { + context.commit('set', response.data) + context.commit('setAllLoaded', false) + context.commit('stopLoading') + }).catch((error) => { + context.commit('stopLoading') + }) + } } diff --git a/routes/api.php b/routes/api.php index 005fe67..9ec4b92 100644 --- a/routes/api.php +++ b/routes/api.php @@ -161,5 +161,10 @@ Route::prefix('content')->name('content.')->group(function () { }); // Templates -Route::get('templates', [TemplateController::class, 'index'])->name('templates.show'); -Route::post('templates', [TemplateController::class, 'create'])->name('templates.create'); +Route::prefix('templates')->group(function () { + Route::get('/', [TemplateController::class, 'index'])->name('templates.index'); + Route::post('/', [TemplateController::class, 'create'])->name('templates.create'); + Route::get('/{slug}', [TemplateController::class, 'show'])->name('templates.show'); + Route::put('/{id}', [TemplateController::class, 'update'])->name('templates.update'); + Route::delete('/{id}', [TemplateController::class, 'destroy'])->name('templates.destroy'); +}); diff --git a/tailwind.config.js b/tailwind.config.js index 0fc804f..a57431c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -21,10 +21,15 @@ module.exports = { '0%, 20%': {transform: 'translateY(0)'}, '8%': {transform: 'translateY(-25%)'}, '16%': {transform: 'translateY(+10%)'} + }, + 'infinite-scroll': { + from: { transform: 'translateX(0)' }, + to: { transform: 'translateX(-100%)' }, } }, animation: { - 'bounce-slow': 'bonce-slow 3s ease-in-out infinite' + 'bounce-slow': 'bonce-slow 3s ease-in-out infinite', + 'infinite-scroll': 'infinite-scroll 50s linear infinite', }, maxHeight: { 42: '10.5rem' diff --git a/tests/Feature/TemplateTest.php b/tests/Feature/TemplateTest.php index 62637b6..624f827 100644 --- a/tests/Feature/TemplateTest.php +++ b/tests/Feature/TemplateTest.php @@ -14,8 +14,10 @@ it('can create template', function () { $templateData = [ 'name' => 'Demo Template', 'slug' => 'demo_template', - 'description' => 'Some description here...', + 'short_description' => 'Short description here...', + 'description' => 'Some long description here...', 'image_url' => 'https://d3ietpyl4f2d18.cloudfront.net/6c35a864-ee3a-4039-80a4-040b6c20ac60/img/pages/welcome/product_cover.jpg', + 'publicly_listed' => true, 'form' => $form->getAttributes(), 'questions' => [['question'=>'Question 1','answer'=>'Answer 1 will be here...']] ]; @@ -23,6 +25,6 @@ it('can create template', function () { ->assertSuccessful() ->assertJson([ 'type' => 'success', - 'message' => 'Template created.' + 'message' => 'Template was created.' ]); });