From 0adce5a2ff72944ea2cc55063d97a3b9ef067a4d Mon Sep 17 00:00:00 2001 From: Julien Nahum Date: Mon, 15 Jan 2024 12:14:47 +0100 Subject: [PATCH] Migrate front-end to Nuxt app (#284) * wip * Managed to load a page * Stuck at changing routes * Fixed the router, and editable div * WIP * Fix app loader * WIP * Fix check-auth middleware * Started to refactor input components * WIP * Added select input, v-click-outside for vselect * update vselect & phone input * Fixed the mixin * input component updates * Fix signature input import * input component updates in vue3 * image input in vue3 * small fixes * fix useFormInput watcher * scale input in vue3 * Vue3: migrating from vuex to Pinia (#249) * Vue3: migrating from vuex to Pinia * toggle input fixes * update configureCompat --------- Co-authored-by: Forms Dev * support vue3 query builder * Refactor inpus * fix: Vue3 Query Builder - Logic Editor (#251) * support vue3 query builder * upgrade * remove local from middleware * Submission table pagination & migrate chart to vue3 (#254) * Submission table Pagination in background * migrate chart to vue3 * Form submissions pagination * Form submissions * Fix form starts * Fix openSelect key issue --------- Co-authored-by: Forms Dev Co-authored-by: Julien Nahum * Vue 3 better animation (#257) * vue-3-better-animation * Working on migration to vueuse/motion * Form sidebar animations * Clean code * Added animations for modal * Finished implementing better animations --------- Co-authored-by: Forms Dev * Work in progress * Migrating amplitude and crisp plugin/composable * Started to refactor pages * WIP * vue3-scroll-shadow-fixes (#260) * WIP * WIP * WIP * Figured out auth & middlewares * WI * Refactoring stores and templates pages to comp. api * Finishing the templates pages * fix collapsible * Finish reworking most templates pages * Reworked workspaces store * Working on home page and modal * Fix dropdown * Fix modal * Fixed form creation * Fixed most of the form/show pages * Updated cors dependency * fix custom domain warning * NuxtLink migration (#262) Co-authored-by: Forms Dev * Tiny fixes + start pre-rendering * migrate-to-nuxt-useappconfig (#263) * migrate-to-nuxt-useappconfig * defineAppConfig --------- Co-authored-by: Forms Dev * Working on form/show and editor * Globally import form inputs to fix resolve * Remove vform - working on form public page * Remove initform mixin * Work in progress for form create guess user * Nuxt Migration notifications (#265) * Nuxt Migration notifications * @input to @update:model-value * change field type fixes * @update:model-value * Enable form-block-logic-editor * vue-confetti migration * PR request changes * useAlert in setup * Migrate to nuxt settings page AND remove axios (#266) * Settings pages migration * remove axios and use opnFetch * Make created form reactive (#267) * Remove verify pages and axios lib --------- Co-authored-by: Julien Nahum * Fix alert styling + bug fixes and cleaning * Refactor notifications + add shadow * Fix vselect issue * Working on page pre-rendering * Created NotionPages store * Added sitemap on nuxt side * Sitemap done, working on aws amplify * Adding missing module * Remove axios and commit backend changes to sitemap * Fix notifications * fix guestpage editor (#269) Co-authored-by: Julien Nahum * Remove appconfig in favor of runtimeconfig * Fixed amplitude bugs, and added staging environment * Added amplify file * Change basdirectory amplify * Fix loading bar position * Fix custom redirect (#273) * Dirty form handling - nuxt migration (#272) * SEO meta nuxt migration (#274) * SEO meta nuxt migration * Polish seo metas, add defaults for OG and twitter --------- Co-authored-by: Julien Nahum * migrate to nuxt useClipboard (#268) * Set middleware on pages (#278) * Se middleware on pages * Se middleware on account page * add robots.txt (#276) * 404 page migration (#277) * Templates pages migration (#275) * NuxtImg Migration (#279) Co-authored-by: Julien Nahum * Update package json * Fix build script * Add loglevel param * Disable page pre-rendering * Attempt to allow svgs * Fix SVGs with NuxtImage * Add .env file at AWS build time * tRGIGGER deploy * Fix issue * ANother attrempt * Fix typo * Fix env? * Attempt to simplify build * Enable swr caching instead of prerenderign * Better image compression * Last attempt at nuxt images efficiency * Improve image optimization again * Remove NuxtImg for non asset files * Restore templates pages cache * Remove useless images + fix templates show page * image optimization caching + fix hydratation issue form template page * URL generation (front&back) + fixed authJWT for SSR * Fix composable issue * Fix form share page * Embeddable form as a nuxt middleware * Fix URL for embeddable middleware * Debugging embeddable on amplify * Add custom domain support * No follow for non-production env * Fix sentry nuxt and custom domain redirect * remove api prefix from routes (#280) * remove api prefix from routes * PR changes --------- Co-authored-by: Julien Nahum * nuxt migration -file upload - WIP (#271) Co-authored-by: Julien Nahum * Fix local file upload * Fix file submissions preview * API redirect to back-end from nuxt * API redirect to back-end from nuxt * Remove old JS app, update deploy script * Fix tests, added gh action nuxt step * Updated package-lock.json * Setup node in GH Nuxt action * Setup client directory for GH workflow --------- Co-authored-by: Forms Dev Co-authored-by: Chirag Chhatrala <60499540+chiragchhatrala@users.noreply.github.com> Co-authored-by: Rishi Raj Jain Co-authored-by: formsdev <136701234+formsdev@users.noreply.github.com> --- .eslintrc.js | 16 - .github/workflows/laravel.yml | 32 +- README.md | 12 +- amplify.yml | 17 + app/Exceptions/Handler.php | 2 +- .../Auth/AppSumoAuthController.php | 8 +- .../Content/FileUploadController.php | 1 + .../Forms/FormSubmissionController.php | 12 +- app/Http/Controllers/SitemapController.php | 60 +- app/Http/Controllers/SpaController.php | 18 - .../Controllers/SubscriptionController.php | 4 +- app/Http/Kernel.php | 9 +- app/Http/Middleware/Authenticate.php | 2 +- app/Http/Middleware/AuthenticateJWT.php | 8 + .../Middleware/CustomDomainRestriction.php | 8 +- app/Http/Middleware/EmbeddableForms.php | 36 - app/Http/Resources/FormSubmissionResource.php | 6 +- app/Jobs/Form/StoreFormSubmissionJob.php | 4 +- app/Models/Forms/Form.php | 4 +- app/Models/Template.php | 2 +- app/Notifications/ResetPassword.php | 2 +- .../FailedPaymentNotification.php | 2 +- app/Providers/RouteServiceProvider.php | 21 +- app/Service/Forms/Webhooks/DiscordHandler.php | 2 +- app/Service/Forms/Webhooks/SlackHandler.php | 2 +- app/helpers.php | 11 + client/.env.example | 13 + client/.gitignore | 25 + client/README.md | 75 + client/app.vue | 101 + client/components/forms/CheckboxInput.vue | 46 + client/components/forms/CodeInput.client.vue | 63 + client/components/forms/ColorInput.vue | 45 + client/components/forms/DateInput.vue | 187 + .../components/forms/FileInput.vue | 70 +- .../components/forms/FlatSelectInput.vue | 45 +- .../components/forms/ImageInput.vue | 73 +- .../components/forms/PhoneInput.vue | 82 +- .../components/forms/RatingInput.vue | 41 +- .../forms/RichTextAreaInput.client.vue | 51 +- .../components/forms/ScaleInput.vue | 45 +- .../components/forms/SelectInput.vue | 71 +- client/components/forms/SignatureInput.vue | 62 + client/components/forms/TextAreaInput.vue | 56 + client/components/forms/TextInput.vue | 77 + client/components/forms/ToggleSwitchInput.vue | 46 + .../components/forms/components/InputHelp.vue | 21 + .../forms/components/InputLabel.vue | 25 + .../forms/components/InputWrapper.vue | 54 + .../forms/components/UploadedFile.vue | 2 +- .../components/forms/components/VCheckbox.vue | 72 + .../components/forms/components/VSelect.vue | 230 + .../components/forms/components/VSwitch.vue | 22 + client/components/forms/useFormInput.js | 88 + .../components/forms/validation/Alert.js | 0 .../forms/validation/AlertError.vue | 0 .../forms/validation/AlertSuccess.vue | 0 .../components/forms/validation/HasError.vue | 2 +- .../components/global}/Breadcrumb.vue | 27 +- .../components/global}/Card.vue | 0 .../components/global}/Collapse.vue | 35 +- client/components/global/Dropdown.vue | 49 + client/components/global/EditableDiv.vue | 72 + .../components/global}/Loader.vue | 0 client/components/global/Modal.vue | 175 + .../components/global}/Navbar.vue | 169 +- client/components/global/Notifications.vue | 105 + client/components/global/NotionPage.vue | 32 + .../components/global}/ProTag.vue | 21 +- .../components/global}/ScrollShadow.vue | 22 +- .../components/global}/Steps.vue | 0 .../components/global/VButton.vue | 20 +- .../components/global}/WorkspaceDropdown.vue | 51 +- .../global/transitions/Collapsible.vue | 52 + .../global}/transitions/VTransition.vue | 4 +- .../open/components/RecordOperations.vue | 20 +- .../open/editors/EditorOptionsPanel.vue | 4 +- .../open/editors/EditorRightSidebar.vue | 32 + .../open/forms/OpenCompleteForm.vue | 107 +- .../components/open/forms/OpenForm.vue | 195 +- .../components/open/forms/OpenFormButton.vue | 6 +- .../components/open/forms/OpenFormField.vue | 57 +- .../components/AdvancedFormUrlSettings.vue | 30 +- .../open/forms/components/CopyContent.vue | 60 +- .../open/forms/components/FormEditor.vue | 158 +- .../forms/components/FormFieldsEditor.vue | 306 + .../open/forms/components/FormStats.vue | 21 +- .../open/forms/components/FormSubmissions.vue | 153 +- .../open/forms/components/FormUrlPrefill.vue | 66 + .../form-components/AddFormBlock.vue | 161 +- .../form-components/FormAboutSubmission.vue | 58 +- .../components/form-components/FormAccess.vue | 11 +- .../form-components/FormCustomCode.vue | 51 + .../form-components/FormCustomSeo.vue | 16 +- .../form-components/FormCustomization.vue | 66 +- .../form-components/FormEditorPreview.vue | 32 +- .../form-components/FormEditorSidebar.vue | 49 + .../form-components/FormErrorModal.vue | 8 +- .../form-components/FormInformation.vue | 49 +- .../form-components/FormNotifications.vue | 30 +- .../form-components/FormSecurityPrivacy.vue | 12 +- .../form-components/FormStructure.vue | 12 +- .../components/FormNotificationsDiscord.vue | 13 +- .../FormNotificationsMessageActions.vue | 0 .../components/FormNotificationsOption.vue | 24 +- .../components/FormNotificationsSlack.vue | 13 +- ...ormNotificationsSubmissionConfirmation.vue | 25 +- .../components/FormNotificationsWebhook.vue | 13 +- .../form-logic-components/ColumnCondition.vue | 19 +- .../form-logic-components/ConditionEditor.vue | 19 +- .../FormBlockLogicEditor.vue | 74 +- .../GroupControlSlot.vue | 2 +- .../templates/FormTemplateModal.vue | 205 +- .../components/templates/QuestionsEditor.vue | 4 +- .../open/forms/fields/FormFieldEdit.vue | 103 +- .../forms/fields/components/BlockOptions.vue | 36 +- .../fields/components/ChangeFieldType.vue | 34 +- .../forms/fields/components/FieldOptions.vue | 242 +- .../components/open/tables/OpenTable.vue | 189 +- .../open/tables/components/OpenCheckbox.vue | 0 .../open/tables/components/OpenDate.vue | 0 .../open/tables/components/OpenFile.vue | 37 +- .../open/tables/components/OpenSelect.vue | 7 +- .../open/tables/components/OpenTag.vue | 0 .../open/tables/components/OpenText.vue | 0 .../open/tables/components/OpenUrl.vue | 0 .../open/tables/components/ResizableTh.vue | 12 +- client/components/pages/OpenFormFooter.vue | 63 + .../pages/auth/ForgotPasswordModal.vue | 6 +- .../pages/auth/components/LoginForm.vue | 117 + .../pages/auth/components/QuickRegister.vue | 0 .../pages/auth/components/RegisterForm.vue | 154 + .../components/pages/forms/NewFeatures.vue | 24 +- .../forms/create/CreateFormBaseModal.vue | 102 +- .../components/pages/forms/show/EmbedCode.vue | 0 .../forms/show/EmbedFormAsPopupModal.vue | 192 +- .../components/pages/forms/show/ExtraMenu.vue | 105 +- .../pages/forms/show/FormCleanings.vue | 10 +- .../pages/forms/show/FormQrCode.vue | 2 +- .../pages/forms/show/RegenerateFormLink.vue | 24 +- .../components/pages/forms/show/ShareLink.vue | 0 .../pages/forms/show/UrlFormPrefill.vue | 8 +- .../pages/pricing/CheckoutDetailsModal.vue | 37 +- .../components/pages/pricing/CustomPlan.vue | 0 .../pages/pricing/MonthlyYearlySelector.vue | 37 + .../components/pages/pricing/PricingTable.vue | 24 +- .../pages/templates/SingleTemplate.vue | 32 +- .../pages/templates/TemplateTags.vue | 47 +- .../pages/templates/TemplatesList.vue | 196 + .../components/pages/welcome/AiFeature.vue | 48 +- .../components/pages/welcome/Features.vue | 11 +- .../components/pages/welcome/MoreFeatures.vue | 0 .../pages/welcome/TemplatesSlider.vue | 84 + .../components/pages/welcome/Testimonials.vue | 12 +- .../components/tools}/StopImpersonation.vue | 30 +- .../vendor/appsumo/AppSumoBilling.vue | 29 +- .../vendor/appsumo/AppSumoRegister.vue | 12 +- client/composables/forms/initForm.js | 54 + client/composables/forms/pendingSubmission.js | 34 + .../forms/validatePropertiesLogic.js | 14 + client/composables/lib/vForm/Errors.js | 75 + client/composables/lib/vForm/Form.js | 170 + client/composables/stores/useContentStore.js | 65 + client/composables/useAlert.js | 51 + client/composables/useAmplitude.js | 40 + client/composables/useConfetti.js | 22 + client/composables/useCrisp.js | 88 + client/composables/useForm.js | 5 + client/composables/useIsIframe.js | 6 + client/composables/useOpnApi.js | 80 + client/composables/useOpnSeoMeta.js | 16 + client/data/country_code_mapper.json | 248 + client/data/country_codes.json | 1232 + client/data/forms/templates/industries.json | 184 + client/data/forms/templates/types.json | 324 + client/data/open_filters.json | 492 + client/data/timezones.json | 1373 + client/error.vue | 25 + {resources/js => client}/layouts/basic.vue | 8 +- client/layouts/default.vue | 8 + client/lib/file-uploads.js | 37 + .../lib}/forms/FormLogicConditionChecker.js | 0 .../lib}/forms/FormLogicPropertyResolver.js | 0 .../lib}/forms/FormPropertyLogicRule.js | 0 .../lib/forms}/form-themes.js | 0 client/lib/forms/public-page.js | 55 + client/lib/utils.js | 76 + client/middleware/01.check-auth.global.js | 16 + client/middleware/admin.js | 7 + client/middleware/api-redirect.global.js | 11 + client/middleware/auth.js | 8 + client/middleware/custom-domain.global.js | 42 + client/middleware/guest.js | 9 + client/middleware/subscribed.js | 7 + .../js => client}/mixins/forms/fieldsLogic.js | 0 .../js => client}/mixins/forms/input.js | 4 +- .../mixins/forms/saveUpdateAlert.js | 4 +- client/nuxt.config.ts | 73 + client/opnform.config.js | 20 + client/package-lock.json | 13281 +++++++++ client/package.json | 60 + .../js => client}/pages/ai-form-builder.vue | 106 +- .../pages/auth/password/email.vue | 27 +- .../pages/auth/password/reset.vue | 31 +- client/pages/forms/[slug]/edit.vue | 106 + client/pages/forms/[slug]/index.vue | 148 + .../pages/forms/[slug]/show.vue | 210 +- client/pages/forms/[slug]/show/index.vue | 7 + client/pages/forms/[slug]/show/share.vue | 55 + .../pages/forms/[slug]}/show/stats.vue | 18 +- .../pages/forms/[slug]/show/submissions.vue | 21 + client/pages/forms/create/guest.vue | 105 + client/pages/forms/create/index.vue | 117 + client/pages/home.vue | 200 + .../welcome.vue => client/pages/index.vue | 148 +- .../js/pages/auth => client/pages}/login.vue | 33 +- {resources/js => client}/pages/pricing.vue | 54 +- client/pages/privacy-policy.vue | 31 + .../pages/auth => client/pages}/register.vue | 25 +- client/pages/settings.vue | 90 + client/pages/settings/account.vue | 48 + client/pages/settings/admin.vue | 80 + client/pages/settings/billing.vue | 49 + client/pages/settings/index.vue | 7 + client/pages/settings/password.vue | 46 + client/pages/settings/profile.vue | 52 + .../pages/settings/workspace.vue | 190 +- client/pages/subscriptions/error.vue | 33 + .../pages/subscriptions/success.vue | 40 +- .../pages/templates/[slug].vue | 241 +- .../pages/templates/index.vue | 36 +- client/pages/templates/industries/[slug].vue | 118 + .../pages/templates/my-templates.vue | 40 +- client/pages/templates/types/[slug].vue | 119 + client/pages/terms-conditions.vue | 31 + client/plugins/amplitude.js | 24 + client/plugins/crisp.client.js | 11 + client/plugins/vue-confetti.client.js | 5 + client/public/favicon.ico | Bin 0 -> 15406 bytes .../fonts/general-sans/GeneralSans-Bold.eot | Bin 0 -> 63986 bytes .../fonts/general-sans/GeneralSans-Bold.ttf | Bin 0 -> 63832 bytes .../fonts/general-sans/GeneralSans-Bold.woff | Bin 0 -> 27860 bytes .../fonts/general-sans/GeneralSans-Bold.woff2 | Bin 0 -> 21180 bytes .../general-sans/GeneralSans-BoldItalic.eot | Bin 0 -> 66232 bytes .../general-sans/GeneralSans-BoldItalic.ttf | Bin 0 -> 66064 bytes .../general-sans/GeneralSans-BoldItalic.woff | Bin 0 -> 28912 bytes .../general-sans/GeneralSans-BoldItalic.woff2 | Bin 0 -> 22228 bytes .../general-sans/GeneralSans-Extralight.eot | Bin 0 -> 64556 bytes .../general-sans/GeneralSans-Extralight.ttf | Bin 0 -> 64360 bytes .../general-sans/GeneralSans-Extralight.woff | Bin 0 -> 26964 bytes .../general-sans/GeneralSans-Extralight.woff2 | Bin 0 -> 20916 bytes .../GeneralSans-ExtralightItalic.eot | Bin 0 -> 66146 bytes .../GeneralSans-ExtralightItalic.ttf | Bin 0 -> 65936 bytes .../GeneralSans-ExtralightItalic.woff | Bin 0 -> 27564 bytes .../GeneralSans-ExtralightItalic.woff2 | Bin 0 -> 21156 bytes .../fonts/general-sans/GeneralSans-Italic.eot | Bin 0 -> 68072 bytes .../fonts/general-sans/GeneralSans-Italic.ttf | Bin 0 -> 67916 bytes .../general-sans/GeneralSans-Italic.woff | Bin 0 -> 31620 bytes .../general-sans/GeneralSans-Italic.woff2 | Bin 0 -> 23988 bytes .../fonts/general-sans/GeneralSans-Light.eot | Bin 0 -> 66678 bytes .../fonts/general-sans/GeneralSans-Light.ttf | Bin 0 -> 66492 bytes .../fonts/general-sans/GeneralSans-Light.woff | Bin 0 -> 30356 bytes .../general-sans/GeneralSans-Light.woff2 | Bin 0 -> 23252 bytes .../general-sans/GeneralSans-LightItalic.eot | Bin 0 -> 68380 bytes .../general-sans/GeneralSans-LightItalic.ttf | Bin 0 -> 68180 bytes .../general-sans/GeneralSans-LightItalic.woff | Bin 0 -> 31756 bytes .../GeneralSans-LightItalic.woff2 | Bin 0 -> 24036 bytes .../fonts/general-sans/GeneralSans-Medium.eot | Bin 0 -> 66100 bytes .../fonts/general-sans/GeneralSans-Medium.ttf | Bin 0 -> 65912 bytes .../general-sans/GeneralSans-Medium.woff | Bin 0 -> 30252 bytes .../general-sans/GeneralSans-Medium.woff2 | Bin 0 -> 22904 bytes .../general-sans/GeneralSans-MediumItalic.eot | Bin 0 -> 68170 bytes .../general-sans/GeneralSans-MediumItalic.ttf | Bin 0 -> 67968 bytes .../GeneralSans-MediumItalic.woff | Bin 0 -> 31620 bytes .../GeneralSans-MediumItalic.woff2 | Bin 0 -> 23856 bytes .../general-sans/GeneralSans-Regular.eot | Bin 0 -> 66436 bytes .../general-sans/GeneralSans-Regular.ttf | Bin 0 -> 66280 bytes .../general-sans/GeneralSans-Regular.woff | Bin 0 -> 30320 bytes .../general-sans/GeneralSans-Regular.woff2 | Bin 0 -> 23084 bytes .../general-sans/GeneralSans-Semibold.eot | Bin 0 -> 65936 bytes .../general-sans/GeneralSans-Semibold.ttf | Bin 0 -> 65744 bytes .../general-sans/GeneralSans-Semibold.woff | Bin 0 -> 30716 bytes .../general-sans/GeneralSans-Semibold.woff2 | Bin 0 -> 23092 bytes .../GeneralSans-SemiboldItalic.eot | Bin 0 -> 67894 bytes .../GeneralSans-SemiboldItalic.ttf | Bin 0 -> 67688 bytes .../GeneralSans-SemiboldItalic.woff | Bin 0 -> 32116 bytes .../GeneralSans-SemiboldItalic.woff2 | Bin 0 -> 24300 bytes .../general-sans/GeneralSans-Variable.eot | Bin 0 -> 111048 bytes .../general-sans/GeneralSans-Variable.ttf | Bin 0 -> 110820 bytes .../general-sans/GeneralSans-Variable.woff | Bin 0 -> 32544 bytes .../general-sans/GeneralSans-Variable.woff2 | Bin 0 -> 38132 bytes .../GeneralSans-VariableItalic.eot | Bin 0 -> 112960 bytes .../GeneralSans-VariableItalic.ttf | Bin 0 -> 112704 bytes .../GeneralSans-VariableItalic.woff | Bin 0 -> 33984 bytes .../GeneralSans-VariableItalic.woff2 | Bin 0 -> 40720 bytes client/public/img/appsumo/as-Select-dark.png | Bin 0 -> 9252 bytes .../public/img/appsumo/as-taco-white-bg.png | Bin 0 -> 9644 bytes client/public/img/customers/dbs.png | Bin 0 -> 4828 bytes client/public/img/customers/harvard.png | Bin 0 -> 8726 bytes client/public/img/customers/hyundai.png | Bin 0 -> 2914 bytes client/public/img/customers/sciencespo.png | Bin 0 -> 4271 bytes client/public/img/customers/yale.png | Bin 0 -> 3183 bytes client/public/img/icons/plant.png | Bin 0 -> 417682 bytes client/public/img/logo.png | Bin 0 -> 7661 bytes client/public/img/logo.svg | 1 + .../ai-feature-illustration.svg | 85 + .../ai_form_builder/background-pattern-ai.svg | 285 + .../ai_form_builder/background-pattern.svg | 78 + .../ai_form_builder/examples-placeholder.png | Bin 0 -> 3211 bytes .../img/pages/ai_form_builder/hero-mockup.png | Bin 0 -> 198861 bytes .../pages/ai_form_builder/icon-browser.svg | 21 + .../img/pages/ai_form_builder/icon-create.svg | 7 + .../ai_form_builder/icon-customization.svg | 12 + .../ai_form_builder/icon-email-input.svg | 12 + .../img/pages/ai_form_builder/icon-fast.svg | 18 + .../ai_form_builder/icon-radio-buttons.svg | 13 + .../img/pages/ai_form_builder/icon-share.svg | 17 + .../pages/ai_form_builder/icon-textarea.svg | 12 + .../img/pages/ai_form_builder/step-1.svg | 262 + .../img/pages/ai_form_builder/step-2.svg | 265 + .../img/pages/ai_form_builder/step-3.svg | 281 + .../pages/create_form/share_notion_db.webm | Bin 0 -> 886095 bytes .../public/img/pages/forms/blurred_graph.png | Bin 0 -> 233451 bytes .../img/pages/forms/search_notfound.png | Bin 0 -> 38836 bytes client/public/img/pages/onboarding/guide.png | Bin 0 -> 118215 bytes .../onboarding/login_with_notion_guide.png | Bin 0 -> 263128 bytes .../public/img/pages/welcome/homebackdrop.png | Bin 0 -> 80373 bytes .../img/pages/welcome/product-cover.jpg | Bin 0 -> 271285 bytes client/public/img/pages/welcome/step-1.jpg | Bin 0 -> 145120 bytes client/public/img/pages/welcome/step-2.jpg | Bin 0 -> 147710 bytes client/public/img/pages/welcome/step-3.jpg | Bin 0 -> 152237 bytes .../img/pages/welcome/tutorial_screenshot.jpg | Bin 0 -> 75304 bytes client/public/img/social-preview.jpg | Bin 0 -> 37277 bytes .../img/tutorial/contact-form-template.png | Bin 0 -> 53909 bytes client/public/img/tutorial/example.gif | Bin 0 -> 838310 bytes .../img/tutorial/integrate_to_notion.gif | Bin 0 -> 1123423 bytes client/public/img/tutorial/share_database.gif | Bin 0 -> 963036 bytes client/public/robots.txt | 2 + client/public/video/opnform-ai.mp4 | Bin 0 -> 3590204 bytes client/public/widgets/embed-min.js | 20 + client/public/widgets/embed.js | 139 + client/runtimeConfig.js | 22 + {resources/sass => client/scss}/app.scss | 0 {resources/sass => client/scss}/fonts.scss | 0 client/server/plugins/embeddable.js | 12 + client/server/tsconfig.json | 3 + client/sitemap.js | 10 + client/stores/app.js | 78 + client/stores/auth.js | 94 + client/stores/errors.js | 15 + client/stores/forms.js | 71 + client/stores/notion_pages.js | 27 + client/stores/records.js | 49 + client/stores/templates.js | 63 + client/stores/working_form.js | 50 + client/stores/workspaces.js | 55 + .../tailwind.config.js | 9 +- client/tsconfig.json | 4 + composer.json | 6 +- composer.lock | 166 +- config/app.php | 9 + config/cors.php | 2 +- config/custom-domains.php | 2 +- package-lock.json | 23781 ---------------- package.json | 74 - postcss.config.js | 6 - resources/js/app.js | 25 - resources/js/base.js | 96 - resources/js/components/App.vue | 128 - resources/js/components/Child.vue | 13 - resources/js/components/Loading.vue | 101 - resources/js/components/LocaleDropdown.vue | 41 - resources/js/components/LoginWithGithub.vue | 92 - resources/js/components/Modal.vue | 151 - resources/js/components/common/Alert.vue | 95 - resources/js/components/common/Dropdown.vue | 54 - .../js/components/common/EditableDiv.vue | 57 - .../js/components/common/Notifications.vue | 139 - resources/js/components/common/index.js | 13 - .../js/components/forms/CheckboxInput.vue | 34 - resources/js/components/forms/CodeInput.vue | 54 - resources/js/components/forms/ColorInput.vue | 25 - resources/js/components/forms/DateInput.vue | 176 - .../js/components/forms/SignatureInput.vue | 62 - .../js/components/forms/TextAreaInput.vue | 51 - resources/js/components/forms/TextInput.vue | 104 - .../js/components/forms/ToggleSwitchInput.vue | 36 - .../components/forms/components/VCheckbox.vue | 79 - .../components/forms/components/VSelect.vue | 244 - .../components/forms/components/VSwitch.vue | 45 - resources/js/components/forms/index.js | 46 - resources/js/components/index.js | 21 - resources/js/components/open/NotionPage.vue | 52 - .../forms/components/FormFieldsEditor.vue | 318 - .../open/forms/components/FormUrlPrefill.vue | 87 - .../form-components/FormCustomCode.vue | 44 - .../js/components/pages/OpenFormFooter.vue | 73 - .../pages/pricing/MonthlyYearlySelector.vue | 41 - .../pages/templates/TemplatesList.vue | 186 - .../pages/welcome/TemplatesSlider.vue | 73 - resources/js/components/service/Amplitude.vue | 97 - resources/js/components/service/Crisp.vue | 33 - resources/js/components/service/Hotjar.vue | 49 - resources/js/lang/de-DE.json | 39 - resources/js/lang/en.json | 39 - resources/js/lang/es.json | 34 - resources/js/lang/fr.json | 39 - resources/js/lang/nb-NO.json | 39 - resources/js/lang/pt-BR.json | 39 - resources/js/lang/zh-CN.json | 34 - resources/js/layouts/default.vue | 50 - resources/js/middleware/admin.js | 9 - resources/js/middleware/auth.js | 12 - resources/js/middleware/check-auth.js | 52 - resources/js/middleware/custom-domains.js | 16 - resources/js/middleware/guest.js | 9 - resources/js/middleware/locale.js | 8 - resources/js/middleware/role.js | 22 - resources/js/middleware/subscribed.js | 9 - resources/js/mixins/form_editor/initForm.js | 57 - .../forms/form-pending-submission-key.js | 22 - resources/js/mixins/seo-meta.js | 23 - .../js/pages/auth/components/LoginForm.vue | 105 - .../js/pages/auth/components/RegisterForm.vue | 145 - .../js/pages/auth/verification/resend.vue | 58 - .../js/pages/auth/verification/verify.vue | 59 - .../community/students-academics-ngos.vue | 35 - resources/js/pages/errors/404.vue | 23 - resources/js/pages/forms/create-guest.vue | 144 - resources/js/pages/forms/create.vue | 153 - resources/js/pages/forms/edit.vue | 135 - resources/js/pages/forms/show-public.vue | 213 - resources/js/pages/forms/show/share.vue | 70 - resources/js/pages/forms/show/submissions.vue | 31 - resources/js/pages/home.vue | 205 - resources/js/pages/integrations.vue | 43 - .../js/pages/legal-help/privacy-policy.vue | 33 - .../js/pages/legal-help/terms-conditions.vue | 33 - resources/js/pages/settings/account.vue | 53 - resources/js/pages/settings/admin.vue | 84 - resources/js/pages/settings/billing.vue | 59 - resources/js/pages/settings/index.vue | 96 - resources/js/pages/settings/password.vue | 49 - resources/js/pages/settings/profile.vue | 57 - resources/js/pages/subscriptions/error.vue | 28 - .../js/pages/templates/industries-show.vue | 232 - resources/js/pages/templates/types-show.vue | 233 - resources/js/plugins/amplitude.js | 37 - resources/js/plugins/axios.js | 52 - .../plugins/config/vue-tailwind/datePicker.js | 19 - resources/js/plugins/i18n.js | 33 - resources/js/plugins/index.js | 5 - resources/js/plugins/sentry.js | 17 - resources/js/plugins/vapor.js | 78 - resources/js/plugins/vue-plugins.js | 7 - resources/js/router/index.js | 259 - resources/js/router/routes.js | 77 - resources/js/store/index.js | 22 - resources/js/store/modules/auth.js | 104 - resources/js/store/modules/blog/guides.js | 35 - resources/js/store/modules/lang.js | 49 - resources/js/store/modules/open/errors.js | 27 - resources/js/store/modules/open/forms.js | 85 - resources/js/store/modules/open/records.js | 58 - resources/js/store/modules/open/templates.js | 126 - .../js/store/modules/open/working_form.js | 49 - resources/js/store/modules/open/workspaces.js | 104 - resources/js/store/mutation-types.js | 10 - .../views/vendor/mail/text/message.blade.php | 2 +- routes/api.php | 36 +- routes/spa.php | 17 - routes/web.php | 43 - tests/Feature/LoginTest.php | 10 +- tests/Feature/RegisterTest.php | 14 +- tests/Feature/SettingsTest.php | 4 +- tests/TestHelpers.php | 2 +- vapor.yml | 59 +- vite.config.js | 57 - 478 files changed, 27676 insertions(+), 34120 deletions(-) delete mode 100644 .eslintrc.js create mode 100644 amplify.yml delete mode 100644 app/Http/Controllers/SpaController.php delete mode 100644 app/Http/Middleware/EmbeddableForms.php create mode 100644 app/helpers.php create mode 100644 client/.env.example create mode 100644 client/.gitignore create mode 100644 client/README.md create mode 100644 client/app.vue create mode 100644 client/components/forms/CheckboxInput.vue create mode 100644 client/components/forms/CodeInput.client.vue create mode 100644 client/components/forms/ColorInput.vue create mode 100644 client/components/forms/DateInput.vue rename {resources/js => client}/components/forms/FileInput.vue (82%) rename {resources/js => client}/components/forms/FlatSelectInput.vue (70%) rename {resources/js => client}/components/forms/ImageInput.vue (81%) rename {resources/js => client}/components/forms/PhoneInput.vue (72%) rename {resources/js => client}/components/forms/RatingInput.vue (66%) rename resources/js/components/forms/RichTextAreaInput.vue => client/components/forms/RichTextAreaInput.client.vue (64%) rename {resources/js => client}/components/forms/ScaleInput.vue (68%) rename {resources/js => client}/components/forms/SelectInput.vue (68%) create mode 100644 client/components/forms/SignatureInput.vue create mode 100644 client/components/forms/TextAreaInput.vue create mode 100644 client/components/forms/TextInput.vue create mode 100644 client/components/forms/ToggleSwitchInput.vue create mode 100644 client/components/forms/components/InputHelp.vue create mode 100644 client/components/forms/components/InputLabel.vue create mode 100644 client/components/forms/components/InputWrapper.vue rename {resources/js => client}/components/forms/components/UploadedFile.vue (98%) create mode 100644 client/components/forms/components/VCheckbox.vue create mode 100644 client/components/forms/components/VSelect.vue create mode 100644 client/components/forms/components/VSwitch.vue create mode 100644 client/components/forms/useFormInput.js rename {resources/js => client}/components/forms/validation/Alert.js (100%) rename {resources/js => client}/components/forms/validation/AlertError.vue (100%) rename {resources/js => client}/components/forms/validation/AlertSuccess.vue (100%) rename {resources/js => client}/components/forms/validation/HasError.vue (93%) rename {resources/js/components/common => client/components/global}/Breadcrumb.vue (82%) rename {resources/js/components/common => client/components/global}/Card.vue (100%) rename {resources/js/components/common => client/components/global}/Collapse.vue (67%) create mode 100644 client/components/global/Dropdown.vue create mode 100644 client/components/global/EditableDiv.vue rename {resources/js/components/common => client/components/global}/Loader.vue (100%) create mode 100644 client/components/global/Modal.vue rename {resources/js/components => client/components/global}/Navbar.vue (53%) create mode 100644 client/components/global/Notifications.vue create mode 100644 client/components/global/NotionPage.vue rename {resources/js/components/common => client/components/global}/ProTag.vue (80%) rename {resources/js/components/common => client/components/global}/ScrollShadow.vue (90%) rename {resources/js/components/common => client/components/global}/Steps.vue (100%) rename resources/js/components/common/Button.vue => client/components/global/VButton.vue (91%) rename {resources/js/components => client/components/global}/WorkspaceDropdown.vue (70%) create mode 100644 client/components/global/transitions/Collapsible.vue rename {resources/js/components/common => client/components/global}/transitions/VTransition.vue (83%) rename {resources/js => client}/components/open/components/RecordOperations.vue (74%) rename {resources/js => client}/components/open/editors/EditorOptionsPanel.vue (88%) create mode 100644 client/components/open/editors/EditorRightSidebar.vue rename {resources/js => client}/components/open/forms/OpenCompleteForm.vue (75%) rename {resources/js => client}/components/open/forms/OpenForm.vue (70%) rename {resources/js => client}/components/open/forms/OpenFormButton.vue (85%) rename {resources/js => client}/components/open/forms/OpenFormField.vue (93%) rename {resources/js => client}/components/open/forms/components/AdvancedFormUrlSettings.vue (53%) rename {resources/js => client}/components/open/forms/components/CopyContent.vue (71%) rename {resources/js => client}/components/open/forms/components/FormEditor.vue (69%) create mode 100644 client/components/open/forms/components/FormFieldsEditor.vue rename {resources/js => client}/components/open/forms/components/FormStats.vue (81%) rename {resources/js => client}/components/open/forms/components/FormSubmissions.vue (62%) create mode 100644 client/components/open/forms/components/FormUrlPrefill.vue rename resources/js/components/open/forms/components/form-components/AddFormBlockSidebar.vue => client/components/open/forms/components/form-components/AddFormBlock.vue (68%) rename {resources/js => client}/components/open/forms/components/form-components/FormAboutSubmission.vue (83%) rename {resources/js => client}/components/open/forms/components/form-components/FormAccess.vue (89%) create mode 100644 client/components/open/forms/components/form-components/FormCustomCode.vue rename {resources/js => client}/components/open/forms/components/form-components/FormCustomSeo.vue (88%) rename {resources/js => client}/components/open/forms/components/form-components/FormCustomization.vue (77%) rename {resources/js => client}/components/open/forms/components/form-components/FormEditorPreview.vue (82%) create mode 100644 client/components/open/forms/components/form-components/FormEditorSidebar.vue rename {resources/js => client}/components/open/forms/components/form-components/FormErrorModal.vue (69%) rename {resources/js => client}/components/open/forms/components/form-components/FormInformation.vue (85%) rename {resources/js => client}/components/open/forms/components/form-components/FormNotifications.vue (88%) rename {resources/js => client}/components/open/forms/components/form-components/FormSecurityPrivacy.vue (82%) rename {resources/js => client}/components/open/forms/components/form-components/FormStructure.vue (88%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsDiscord.vue (91%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsMessageActions.vue (100%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsOption.vue (89%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsSlack.vue (91%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsSubmissionConfirmation.vue (82%) rename {resources/js => client}/components/open/forms/components/form-components/components/FormNotificationsWebhook.vue (91%) rename {resources/js => client}/components/open/forms/components/form-logic-components/ColumnCondition.vue (89%) rename {resources/js => client}/components/open/forms/components/form-logic-components/ConditionEditor.vue (83%) rename {resources/js => client}/components/open/forms/components/form-logic-components/FormBlockLogicEditor.vue (78%) rename {resources/js => client}/components/open/forms/components/form-logic-components/GroupControlSlot.vue (95%) rename {resources/js => client}/components/open/forms/components/templates/FormTemplateModal.vue (55%) rename {resources/js => client}/components/open/forms/components/templates/QuestionsEditor.vue (97%) rename resources/js/components/open/forms/fields/FormFieldEditSidebar.vue => client/components/open/forms/fields/FormFieldEdit.vue (67%) rename {resources/js => client}/components/open/forms/fields/components/BlockOptions.vue (81%) rename {resources/js => client}/components/open/forms/fields/components/ChangeFieldType.vue (66%) rename {resources/js => client}/components/open/forms/fields/components/FieldOptions.vue (72%) rename {resources/js => client}/components/open/tables/OpenTable.vue (61%) rename {resources/js => client}/components/open/tables/components/OpenCheckbox.vue (100%) rename {resources/js => client}/components/open/tables/components/OpenDate.vue (100%) rename {resources/js => client}/components/open/tables/components/OpenFile.vue (55%) rename {resources/js => client}/components/open/tables/components/OpenSelect.vue (76%) rename {resources/js => client}/components/open/tables/components/OpenTag.vue (100%) rename {resources/js => client}/components/open/tables/components/OpenText.vue (100%) rename {resources/js => client}/components/open/tables/components/OpenUrl.vue (100%) rename {resources/js => client}/components/open/tables/components/ResizableTh.vue (77%) create mode 100644 client/components/pages/OpenFormFooter.vue rename {resources/js => client/components}/pages/auth/ForgotPasswordModal.vue (97%) create mode 100644 client/components/pages/auth/components/LoginForm.vue rename {resources/js => client/components}/pages/auth/components/QuickRegister.vue (100%) create mode 100644 client/components/pages/auth/components/RegisterForm.vue rename {resources/js => client}/components/pages/forms/NewFeatures.vue (86%) rename {resources/js => client}/components/pages/forms/create/CreateFormBaseModal.vue (66%) rename {resources/js => client}/components/pages/forms/show/EmbedCode.vue (100%) rename {resources/js => client}/components/pages/forms/show/EmbedFormAsPopupModal.vue (52%) rename {resources/js => client}/components/pages/forms/show/ExtraMenu.vue (79%) rename {resources/js => client}/components/pages/forms/show/FormCleanings.vue (93%) rename {resources/js => client}/components/pages/forms/show/FormQrCode.vue (98%) rename {resources/js => client}/components/pages/forms/show/RegenerateFormLink.vue (85%) rename {resources/js => client}/components/pages/forms/show/ShareLink.vue (100%) rename {resources/js => client}/components/pages/forms/show/UrlFormPrefill.vue (95%) rename {resources/js => client}/components/pages/pricing/CheckoutDetailsModal.vue (71%) rename {resources/js => client}/components/pages/pricing/CustomPlan.vue (100%) create mode 100644 client/components/pages/pricing/MonthlyYearlySelector.vue rename {resources/js => client}/components/pages/pricing/PricingTable.vue (94%) rename {resources/js => client}/components/pages/templates/SingleTemplate.vue (77%) rename {resources/js => client}/components/pages/templates/TemplateTags.vue (67%) create mode 100644 client/components/pages/templates/TemplatesList.vue rename {resources/js => client}/components/pages/welcome/AiFeature.vue (76%) rename {resources/js => client}/components/pages/welcome/Features.vue (96%) rename {resources/js => client}/components/pages/welcome/MoreFeatures.vue (100%) create mode 100644 client/components/pages/welcome/TemplatesSlider.vue rename {resources/js => client}/components/pages/welcome/Testimonials.vue (83%) rename {resources/js/components/pages => client/components/tools}/StopImpersonation.vue (67%) rename {resources/js => client}/components/vendor/appsumo/AppSumoBilling.vue (78%) rename {resources/js => client}/components/vendor/appsumo/AppSumoRegister.vue (73%) create mode 100644 client/composables/forms/initForm.js create mode 100644 client/composables/forms/pendingSubmission.js create mode 100644 client/composables/forms/validatePropertiesLogic.js create mode 100644 client/composables/lib/vForm/Errors.js create mode 100644 client/composables/lib/vForm/Form.js create mode 100644 client/composables/stores/useContentStore.js create mode 100644 client/composables/useAlert.js create mode 100644 client/composables/useAmplitude.js create mode 100644 client/composables/useConfetti.js create mode 100644 client/composables/useCrisp.js create mode 100644 client/composables/useForm.js create mode 100644 client/composables/useIsIframe.js create mode 100644 client/composables/useOpnApi.js create mode 100644 client/composables/useOpnSeoMeta.js create mode 100644 client/data/country_code_mapper.json create mode 100644 client/data/country_codes.json create mode 100644 client/data/forms/templates/industries.json create mode 100644 client/data/forms/templates/types.json create mode 100644 client/data/open_filters.json create mode 100644 client/data/timezones.json create mode 100644 client/error.vue rename {resources/js => client}/layouts/basic.vue (84%) create mode 100644 client/layouts/default.vue create mode 100644 client/lib/file-uploads.js rename {resources/js => client/lib}/forms/FormLogicConditionChecker.js (100%) rename {resources/js => client/lib}/forms/FormLogicPropertyResolver.js (100%) rename {resources/js => client/lib}/forms/FormPropertyLogicRule.js (100%) rename {resources/js/config => client/lib/forms}/form-themes.js (100%) create mode 100644 client/lib/forms/public-page.js create mode 100644 client/lib/utils.js create mode 100644 client/middleware/01.check-auth.global.js create mode 100644 client/middleware/admin.js create mode 100644 client/middleware/api-redirect.global.js create mode 100644 client/middleware/auth.js create mode 100644 client/middleware/custom-domain.global.js create mode 100644 client/middleware/guest.js create mode 100644 client/middleware/subscribed.js rename {resources/js => client}/mixins/forms/fieldsLogic.js (100%) rename {resources/js => client}/mixins/forms/input.js (94%) rename {resources/js => client}/mixins/forms/saveUpdateAlert.js (70%) create mode 100644 client/nuxt.config.ts create mode 100644 client/opnform.config.js create mode 100644 client/package-lock.json create mode 100644 client/package.json rename {resources/js => client}/pages/ai-form-builder.vue (88%) rename {resources/js => client}/pages/auth/password/email.vue (58%) rename {resources/js => client}/pages/auth/password/reset.vue (64%) create mode 100644 client/pages/forms/[slug]/edit.vue create mode 100644 client/pages/forms/[slug]/index.vue rename resources/js/pages/forms/show/index.vue => client/pages/forms/[slug]/show.vue (60%) create mode 100644 client/pages/forms/[slug]/show/index.vue create mode 100644 client/pages/forms/[slug]/show/share.vue rename {resources/js/pages/forms => client/pages/forms/[slug]}/show/stats.vue (50%) create mode 100644 client/pages/forms/[slug]/show/submissions.vue create mode 100644 client/pages/forms/create/guest.vue create mode 100644 client/pages/forms/create/index.vue create mode 100644 client/pages/home.vue rename resources/js/pages/welcome.vue => client/pages/index.vue (75%) rename {resources/js/pages/auth => client/pages}/login.vue (84%) rename {resources/js => client}/pages/pricing.vue (95%) create mode 100644 client/pages/privacy-policy.vue rename {resources/js/pages/auth => client/pages}/register.vue (83%) create mode 100644 client/pages/settings.vue create mode 100644 client/pages/settings/account.vue create mode 100644 client/pages/settings/admin.vue create mode 100644 client/pages/settings/billing.vue create mode 100644 client/pages/settings/index.vue create mode 100644 client/pages/settings/password.vue create mode 100644 client/pages/settings/profile.vue rename {resources/js => client}/pages/settings/workspace.vue (56%) create mode 100644 client/pages/subscriptions/error.vue rename {resources/js => client}/pages/subscriptions/success.vue (64%) rename resources/js/pages/templates/show.vue => client/pages/templates/[slug].vue (60%) rename resources/js/pages/templates/templates.vue => client/pages/templates/index.vue (53%) create mode 100644 client/pages/templates/industries/[slug].vue rename resources/js/pages/templates/my_templates.vue => client/pages/templates/my-templates.vue (53%) create mode 100644 client/pages/templates/types/[slug].vue create mode 100644 client/pages/terms-conditions.vue create mode 100644 client/plugins/amplitude.js create mode 100644 client/plugins/crisp.client.js create mode 100644 client/plugins/vue-confetti.client.js create mode 100644 client/public/favicon.ico create mode 100644 client/public/fonts/general-sans/GeneralSans-Bold.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Bold.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Bold.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Bold.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-BoldItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-BoldItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-BoldItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-BoldItalic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Extralight.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Extralight.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Extralight.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Extralight.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-ExtralightItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-ExtralightItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-ExtralightItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-ExtralightItalic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Italic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Italic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Italic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Italic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Light.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Light.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Light.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Light.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-LightItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-LightItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-LightItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-LightItalic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Medium.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Medium.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Medium.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Medium.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-MediumItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-MediumItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-MediumItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-MediumItalic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Regular.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Regular.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Regular.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Regular.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Semibold.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Semibold.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Semibold.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Semibold.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-SemiboldItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-SemiboldItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-SemiboldItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-SemiboldItalic.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-Variable.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-Variable.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-Variable.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-Variable.woff2 create mode 100644 client/public/fonts/general-sans/GeneralSans-VariableItalic.eot create mode 100644 client/public/fonts/general-sans/GeneralSans-VariableItalic.ttf create mode 100644 client/public/fonts/general-sans/GeneralSans-VariableItalic.woff create mode 100644 client/public/fonts/general-sans/GeneralSans-VariableItalic.woff2 create mode 100644 client/public/img/appsumo/as-Select-dark.png create mode 100644 client/public/img/appsumo/as-taco-white-bg.png create mode 100644 client/public/img/customers/dbs.png create mode 100644 client/public/img/customers/harvard.png create mode 100644 client/public/img/customers/hyundai.png create mode 100644 client/public/img/customers/sciencespo.png create mode 100644 client/public/img/customers/yale.png create mode 100644 client/public/img/icons/plant.png create mode 100644 client/public/img/logo.png create mode 100644 client/public/img/logo.svg create mode 100644 client/public/img/pages/ai_form_builder/ai-feature-illustration.svg create mode 100644 client/public/img/pages/ai_form_builder/background-pattern-ai.svg create mode 100644 client/public/img/pages/ai_form_builder/background-pattern.svg create mode 100644 client/public/img/pages/ai_form_builder/examples-placeholder.png create mode 100644 client/public/img/pages/ai_form_builder/hero-mockup.png create mode 100644 client/public/img/pages/ai_form_builder/icon-browser.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-create.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-customization.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-email-input.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-fast.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-radio-buttons.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-share.svg create mode 100644 client/public/img/pages/ai_form_builder/icon-textarea.svg create mode 100644 client/public/img/pages/ai_form_builder/step-1.svg create mode 100644 client/public/img/pages/ai_form_builder/step-2.svg create mode 100644 client/public/img/pages/ai_form_builder/step-3.svg create mode 100644 client/public/img/pages/create_form/share_notion_db.webm create mode 100644 client/public/img/pages/forms/blurred_graph.png create mode 100644 client/public/img/pages/forms/search_notfound.png create mode 100644 client/public/img/pages/onboarding/guide.png create mode 100644 client/public/img/pages/onboarding/login_with_notion_guide.png create mode 100644 client/public/img/pages/welcome/homebackdrop.png create mode 100644 client/public/img/pages/welcome/product-cover.jpg create mode 100644 client/public/img/pages/welcome/step-1.jpg create mode 100644 client/public/img/pages/welcome/step-2.jpg create mode 100644 client/public/img/pages/welcome/step-3.jpg create mode 100644 client/public/img/pages/welcome/tutorial_screenshot.jpg create mode 100644 client/public/img/social-preview.jpg create mode 100644 client/public/img/tutorial/contact-form-template.png create mode 100644 client/public/img/tutorial/example.gif create mode 100644 client/public/img/tutorial/integrate_to_notion.gif create mode 100644 client/public/img/tutorial/share_database.gif create mode 100644 client/public/robots.txt create mode 100644 client/public/video/opnform-ai.mp4 create mode 100644 client/public/widgets/embed-min.js create mode 100644 client/public/widgets/embed.js create mode 100644 client/runtimeConfig.js rename {resources/sass => client/scss}/app.scss (100%) rename {resources/sass => client/scss}/fonts.scss (100%) create mode 100644 client/server/plugins/embeddable.js create mode 100644 client/server/tsconfig.json create mode 100644 client/sitemap.js create mode 100644 client/stores/app.js create mode 100644 client/stores/auth.js create mode 100644 client/stores/errors.js create mode 100644 client/stores/forms.js create mode 100644 client/stores/notion_pages.js create mode 100644 client/stores/records.js create mode 100644 client/stores/templates.js create mode 100644 client/stores/working_form.js create mode 100644 client/stores/workspaces.js rename tailwind.config.js => client/tailwind.config.js (93%) create mode 100644 client/tsconfig.json delete mode 100644 package-lock.json delete mode 100644 package.json delete mode 100644 postcss.config.js delete mode 100644 resources/js/app.js delete mode 100644 resources/js/base.js delete mode 100644 resources/js/components/App.vue delete mode 100644 resources/js/components/Child.vue delete mode 100644 resources/js/components/Loading.vue delete mode 100644 resources/js/components/LocaleDropdown.vue delete mode 100644 resources/js/components/LoginWithGithub.vue delete mode 100644 resources/js/components/Modal.vue delete mode 100644 resources/js/components/common/Alert.vue delete mode 100644 resources/js/components/common/Dropdown.vue delete mode 100644 resources/js/components/common/EditableDiv.vue delete mode 100644 resources/js/components/common/Notifications.vue delete mode 100644 resources/js/components/common/index.js delete mode 100644 resources/js/components/forms/CheckboxInput.vue delete mode 100644 resources/js/components/forms/CodeInput.vue delete mode 100644 resources/js/components/forms/ColorInput.vue delete mode 100644 resources/js/components/forms/DateInput.vue delete mode 100644 resources/js/components/forms/SignatureInput.vue delete mode 100644 resources/js/components/forms/TextAreaInput.vue delete mode 100644 resources/js/components/forms/TextInput.vue delete mode 100644 resources/js/components/forms/ToggleSwitchInput.vue delete mode 100644 resources/js/components/forms/components/VCheckbox.vue delete mode 100644 resources/js/components/forms/components/VSelect.vue delete mode 100644 resources/js/components/forms/components/VSwitch.vue delete mode 100644 resources/js/components/forms/index.js delete mode 100644 resources/js/components/index.js delete mode 100644 resources/js/components/open/NotionPage.vue delete mode 100644 resources/js/components/open/forms/components/FormFieldsEditor.vue delete mode 100644 resources/js/components/open/forms/components/FormUrlPrefill.vue delete mode 100644 resources/js/components/open/forms/components/form-components/FormCustomCode.vue delete mode 100644 resources/js/components/pages/OpenFormFooter.vue delete mode 100644 resources/js/components/pages/pricing/MonthlyYearlySelector.vue delete mode 100644 resources/js/components/pages/templates/TemplatesList.vue delete mode 100644 resources/js/components/pages/welcome/TemplatesSlider.vue delete mode 100644 resources/js/components/service/Amplitude.vue delete mode 100644 resources/js/components/service/Crisp.vue delete mode 100644 resources/js/components/service/Hotjar.vue delete mode 100644 resources/js/lang/de-DE.json delete mode 100644 resources/js/lang/en.json delete mode 100644 resources/js/lang/es.json delete mode 100644 resources/js/lang/fr.json delete mode 100644 resources/js/lang/nb-NO.json delete mode 100644 resources/js/lang/pt-BR.json delete mode 100644 resources/js/lang/zh-CN.json delete mode 100644 resources/js/layouts/default.vue delete mode 100644 resources/js/middleware/admin.js delete mode 100644 resources/js/middleware/auth.js delete mode 100644 resources/js/middleware/check-auth.js delete mode 100644 resources/js/middleware/custom-domains.js delete mode 100644 resources/js/middleware/guest.js delete mode 100644 resources/js/middleware/locale.js delete mode 100644 resources/js/middleware/role.js delete mode 100644 resources/js/middleware/subscribed.js delete mode 100644 resources/js/mixins/form_editor/initForm.js delete mode 100644 resources/js/mixins/forms/form-pending-submission-key.js delete mode 100644 resources/js/mixins/seo-meta.js delete mode 100644 resources/js/pages/auth/components/LoginForm.vue delete mode 100644 resources/js/pages/auth/components/RegisterForm.vue delete mode 100644 resources/js/pages/auth/verification/resend.vue delete mode 100644 resources/js/pages/auth/verification/verify.vue delete mode 100644 resources/js/pages/community/students-academics-ngos.vue delete mode 100644 resources/js/pages/errors/404.vue delete mode 100644 resources/js/pages/forms/create-guest.vue delete mode 100644 resources/js/pages/forms/create.vue delete mode 100644 resources/js/pages/forms/edit.vue delete mode 100644 resources/js/pages/forms/show-public.vue delete mode 100644 resources/js/pages/forms/show/share.vue delete mode 100644 resources/js/pages/forms/show/submissions.vue delete mode 100644 resources/js/pages/home.vue delete mode 100644 resources/js/pages/integrations.vue delete mode 100644 resources/js/pages/legal-help/privacy-policy.vue delete mode 100644 resources/js/pages/legal-help/terms-conditions.vue delete mode 100644 resources/js/pages/settings/account.vue delete mode 100644 resources/js/pages/settings/admin.vue delete mode 100644 resources/js/pages/settings/billing.vue delete mode 100644 resources/js/pages/settings/index.vue delete mode 100644 resources/js/pages/settings/password.vue delete mode 100644 resources/js/pages/settings/profile.vue delete mode 100644 resources/js/pages/subscriptions/error.vue delete mode 100644 resources/js/pages/templates/industries-show.vue delete mode 100644 resources/js/pages/templates/types-show.vue delete mode 100644 resources/js/plugins/amplitude.js delete mode 100644 resources/js/plugins/axios.js delete mode 100644 resources/js/plugins/config/vue-tailwind/datePicker.js delete mode 100644 resources/js/plugins/i18n.js delete mode 100644 resources/js/plugins/index.js delete mode 100644 resources/js/plugins/sentry.js delete mode 100644 resources/js/plugins/vapor.js delete mode 100644 resources/js/plugins/vue-plugins.js delete mode 100644 resources/js/router/index.js delete mode 100644 resources/js/router/routes.js delete mode 100644 resources/js/store/index.js delete mode 100644 resources/js/store/modules/auth.js delete mode 100644 resources/js/store/modules/blog/guides.js delete mode 100644 resources/js/store/modules/lang.js delete mode 100644 resources/js/store/modules/open/errors.js delete mode 100644 resources/js/store/modules/open/forms.js delete mode 100644 resources/js/store/modules/open/records.js delete mode 100644 resources/js/store/modules/open/templates.js delete mode 100644 resources/js/store/modules/open/working_form.js delete mode 100644 resources/js/store/modules/open/workspaces.js delete mode 100644 resources/js/store/mutation-types.js delete mode 100644 routes/spa.php delete mode 100644 routes/web.php delete mode 100644 vite.config.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 1562093..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - root: true, - parser: 'vue-eslint-parser', - parserOptions: { - parser: '@babel/eslint-parser', - ecmaVersion: 2018, - sourceType: 'module' - }, - extends: [ - 'plugin:vue/recommended', - 'standard' - ], - rules: { - 'vue/max-attributes-per-line': 'off' - } -} diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 6d24a2b..deaff2d 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -86,13 +86,6 @@ jobs: restore-keys: | ${{ runner.os }}-composer- - - uses: actions/cache@v2 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -128,6 +121,31 @@ jobs: path: storage/logs/laravel.log retention-days: 3 + build-nuxt-app: + runs-on: ubuntu-latest + name: Build the Nuxt app + defaults: + run: + working-directory: ./client + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v1 + with: + node-version: '20' + + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Prepare the environment + run: cp .env.example .env + - name: Install npm dependencies run: npm install --no-audit --no-progress --silent diff --git a/README.md b/README.md index ec84b07..087db45 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ It takes 1 minute to try out the builder for free. You'll have high availability ### Docker installation 🐳 -There's a `Dockerfile` for building a self-contained docker image including databases, webservers etc. +> ⚠️ **Warning**: the Docker setup is currently not working as we're migrating the front-end to Nuxt. [Track progress here](https://github.com/JhumanJ/OpnForm/issues/283). This can be built and run locally but is also hosted publicly on docker hub at `jhumanj/opnform` and is generally best run directly from there. @@ -154,8 +154,11 @@ First, let's work with the codebase and its dependencies. # Get the code! git clone git@github.com:JhumanJ/OpnForm.git && cd OpnForm -# Install PHP and JS dependencies -composer install && npm install +# Install PHP dependencies +composer install + + # Install JS dependencies +cd client && npm install # Compile assets (see the scripts section in package.json) npm run dev # or build @@ -186,7 +189,8 @@ Now, create an S3 bucket (or equivalent). Create an IAM user with access to this OpnForm is a standard web application built with: - [Laravel](https://laravel.com/) PHP framework -- [Vue.js](https://vuejs.org/) front-end framework +- [NuxtJs](https://nuxt.com/) Front-end SSR framework +- [Vue.js 3](https://vuejs.org/) Front-end framework - [TailwindCSS](https://tailwindcss.com/) ## Contribute diff --git a/amplify.yml b/amplify.yml new file mode 100644 index 0000000..5b6affd --- /dev/null +++ b/amplify.yml @@ -0,0 +1,17 @@ +version: 1 +frontend: + phases: + preBuild: + commands: + - cd client + - npm ci + build: + commands: + - npm run build + artifacts: + baseDirectory: client/.amplify-hosting + files: + - '**/*' + cache: + paths: + - client/node_modules/**/* diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 830207d..966ea02 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -48,7 +48,7 @@ class Handler extends ExceptionHandler { return $request->expectsJson() ? response()->json(['message' => $exception->getMessage()], 401) - : redirect()->guest(url('/login')); + : redirect(front_url('login')); } public function report(Throwable $exception) diff --git a/app/Http/Controllers/Auth/AppSumoAuthController.php b/app/Http/Controllers/Auth/AppSumoAuthController.php index 505d2d9..a5cd5aa 100644 --- a/app/Http/Controllers/Auth/AppSumoAuthController.php +++ b/app/Http/Controllers/Auth/AppSumoAuthController.php @@ -28,10 +28,10 @@ class AppSumoAuthController extends Controller // otherwise start login flow by passing the encrypted license key id if (is_null($license->user_id)) { - return redirect(url('/register?appsumo_license='.encrypt($license->id))); + return redirect(front_url('/register?appsumo_license='.encrypt($license->id))); } - return redirect(url('/register?appsumo_error=1')); + return redirect(front_url('/register?appsumo_error=1')); } private function retrieveAccessToken(string $requestCode): string @@ -82,11 +82,11 @@ class AppSumoAuthController extends Controller if (is_null($license->user_id)) { $license->user_id = Auth::id(); $license->save(); - return redirect(url('/home?appsumo_connect=1')); + return redirect(front_url('/home?appsumo_connect=1')); } // Licensed already attached - return redirect(url('/home?appsumo_error=1')); + return redirect(front_url('/home?appsumo_error=1')); } /** diff --git a/app/Http/Controllers/Content/FileUploadController.php b/app/Http/Controllers/Content/FileUploadController.php index 62e6423..3481d8c 100644 --- a/app/Http/Controllers/Content/FileUploadController.php +++ b/app/Http/Controllers/Content/FileUploadController.php @@ -17,6 +17,7 @@ class FileUploadController extends Controller */ public function upload(Request $request) { + $request->validate(['file' => 'required|file']); $uuid = (string) Str::uuid(); $path = $request->file('file')->storeAs(PublicFormController::TMP_FILE_UPLOAD_PATH, $uuid); diff --git a/app/Http/Controllers/Forms/FormSubmissionController.php b/app/Http/Controllers/Forms/FormSubmissionController.php index 75d1a90..dca04b1 100644 --- a/app/Http/Controllers/Forms/FormSubmissionController.php +++ b/app/Http/Controllers/Forms/FormSubmissionController.php @@ -15,7 +15,8 @@ class FormSubmissionController extends Controller { public function __construct() { - $this->middleware('auth'); + $this->middleware('auth', ['except' => ['submissionFile']]); + $this->middleware('signed', ['only' => ['submissionFile']]); } public function submissions(string $id) @@ -51,9 +52,6 @@ class FormSubmissionController extends Controller public function submissionFile($id, $fileName) { - $form = Form::findOrFail((int) $id); - $this->authorize('view', $form); - $fileName = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $id).'/' .urldecode($fileName); @@ -63,8 +61,12 @@ class FormSubmissionController extends Controller ], 404); } + if (config('filesystems.default') !== 's3') { + return response()->file(Storage::path($fileName)); + } + return redirect( - Storage::temporaryUrl($fileName, now()->addMinute()) + Storage::temporaryUrl($fileName, now()->addMinute()) ); } } diff --git a/app/Http/Controllers/SitemapController.php b/app/Http/Controllers/SitemapController.php index 1c624e0..712073e 100644 --- a/app/Http/Controllers/SitemapController.php +++ b/app/Http/Controllers/SitemapController.php @@ -9,62 +9,24 @@ use App\Models\Template; class SitemapController extends Controller { - /** - * Contains route name and the associated priority - * - * @var array - */ - protected $urls = [ - ['/', 1], - ['/pricing', 0.9], - ['/privacy-policy', 0.5], - ['/terms-conditions', 0.5], - ['/login', 0.4], - ['/register', 0.4], - ['/password/reset', 0.3], - ['/form-templates', 0.9], - ]; - public function getSitemap(Request $request) + public function index(Request $request) { - $sitemap = Sitemap::create(); - foreach ($this->urls as $url) { - $sitemap->add($this->createUrl($url[0], $url[1])); - } - $this->addTemplatesUrls($sitemap); - $this->addTemplatesTypesUrls($sitemap); - $this->addTemplatesIndustriesUrls($sitemap); - - return $sitemap->toResponse($request); + return [ + ...$this->getTemplatesUrls() + ]; } - private function createUrl($url, $priority, $frequency = 'daily') + private function getTemplatesUrls() { - return Url::create($url)->setPriority($priority)->setChangeFrequency($frequency); - } - - private function addTemplatesUrls(Sitemap $sitemap) - { - Template::where('publicly_listed', true)->chunk(100, function ($templates) use ($sitemap) { + $urls = []; + Template::where('publicly_listed', true)->chunk(100, function ($templates) use (&$urls) { foreach ($templates as $template) { - $sitemap->add($this->createUrl('/form-templates/' . $template->slug, 0.8)); + $urls[] = [ + 'loc' => '/templates/' . $template->slug + ]; } }); - } - - private function addTemplatesTypesUrls(Sitemap $sitemap) - { - $types = json_decode(file_get_contents(resource_path('data/forms/templates/types.json')), true); - foreach ($types as $type) { - $sitemap->add($this->createUrl('/form-templates/types/' . $type['slug'], 0.7)); - } - } - - private function addTemplatesIndustriesUrls(Sitemap $sitemap) - { - $industries = json_decode(file_get_contents(resource_path('data/forms/templates/industries.json')), true); - foreach ($industries as $industry) { - $sitemap->add($this->createUrl('/form-templates/industries/' . $industry['slug'], 0.7)); - } + return $urls; } } diff --git a/app/Http/Controllers/SpaController.php b/app/Http/Controllers/SpaController.php deleted file mode 100644 index 50456f1..0000000 --- a/app/Http/Controllers/SpaController.php +++ /dev/null @@ -1,18 +0,0 @@ - (new SeoMetaResolver($request))->getMetas(), - ]); - } -} diff --git a/app/Http/Controllers/SubscriptionController.php b/app/Http/Controllers/SubscriptionController.php index 4205b36..8cc0213 100644 --- a/app/Http/Controllers/SubscriptionController.php +++ b/app/Http/Controllers/SubscriptionController.php @@ -45,8 +45,8 @@ class SubscriptionController extends Controller $checkout = $checkoutBuilder ->collectTaxIds() ->checkout([ - 'success_url' => url('/subscriptions/success'), - 'cancel_url' => url('/subscriptions/error'), + 'success_url' => front_url('/subscriptions/success'), + 'cancel_url' => front_url('/subscriptions/error'), 'billing_address_collection' => 'required', 'customer_update' => [ 'address' => 'auto', diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 556e49c..1ae7aeb 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -4,7 +4,6 @@ namespace App\Http; use App\Http\Middleware\AuthenticateJWT; use App\Http\Middleware\CustomDomainRestriction; -use App\Http\Middleware\EmbeddableForms; use App\Http\Middleware\IsAdmin; use App\Http\Middleware\IsNotSubscribed; use App\Http\Middleware\IsSubscribed; @@ -20,9 +19,9 @@ class Kernel extends HttpKernel * @var array */ protected $middleware = [ - // \App\Http\Middleware\TrustHosts::class, +// \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, - \Fruitcake\Cors\HandleCors::class, + \Illuminate\Http\Middleware\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, @@ -46,16 +45,14 @@ class Kernel extends HttpKernel \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, - EmbeddableForms::class ], 'spa' => [ \Illuminate\Routing\Middleware\SubstituteBindings::class, - EmbeddableForms::class ], 'api' => [ - 'throttle:60,1', + 'throttle:100,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Session\Middleware\StartSession::class, diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 513b77e..b481f9f 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -15,7 +15,7 @@ class Authenticate extends Middleware protected function redirectTo($request) { if (! $request->expectsJson()) { - return redirect('/login'); + return redirect(front_url('login')); } } } diff --git a/app/Http/Middleware/AuthenticateJWT.php b/app/Http/Middleware/AuthenticateJWT.php index 7fc10ef..8cbc86b 100644 --- a/app/Http/Middleware/AuthenticateJWT.php +++ b/app/Http/Middleware/AuthenticateJWT.php @@ -8,6 +8,7 @@ use Tymon\JWTAuth\Exceptions\JWTException; class AuthenticateJWT { + const API_SERVER_SECRET_HEADER_NAME = 'x-api-secret'; /** * Verifies the JWT token and validates the IP and User Agent @@ -24,6 +25,13 @@ class AuthenticateJWT // Validate IP and User Agent if ($payload) { + if ($frontApiSecret = $request->header(self::API_SERVER_SECRET_HEADER_NAME)) { + // If it's a trusted SSR request, skip the rest + if ($frontApiSecret === config('app.front_api_secret')) { + return $next($request); + } + } + $error = null; if (!\Hash::check($request->ip(), $payload->get('ip'))) { $error = 'Origin IP is invalid'; diff --git a/app/Http/Middleware/CustomDomainRestriction.php b/app/Http/Middleware/CustomDomainRestriction.php index 9553f27..31f4b0e 100644 --- a/app/Http/Middleware/CustomDomainRestriction.php +++ b/app/Http/Middleware/CustomDomainRestriction.php @@ -11,7 +11,7 @@ use Illuminate\Database\Eloquent\Builder; class CustomDomainRestriction { - const CUSTOM_DOMAIN_HEADER = "User-Custom-Domain"; + const CUSTOM_DOMAIN_HEADER = "x-custom-domain"; /** * Handle an incoming request. @@ -27,7 +27,8 @@ class CustomDomainRestriction return response()->json([ 'success' => false, 'message' => 'Invalid domain', - ], 400); + 'error' => 'invalid_domain', + ], 420); } // Check if domain is different from current domain @@ -41,7 +42,8 @@ class CustomDomainRestriction return response()->json([ 'success' => false, 'message' => 'Unknown domain', - ], 400); + 'error' => 'invalid_domain', + ], 420); } Workspace::addGlobalScope('domain-restricted', function (Builder $builder) use ($workspace) { diff --git a/app/Http/Middleware/EmbeddableForms.php b/app/Http/Middleware/EmbeddableForms.php deleted file mode 100644 index e571fc4..0000000 --- a/app/Http/Middleware/EmbeddableForms.php +++ /dev/null @@ -1,36 +0,0 @@ -expectsJson() || $request->wantsJson()) { - return $next($request); - } - - $response = $next($request); - - if (!str_starts_with($request->url(), url('/forms/'))) { - if ($response instanceof Response) { - $response->header('X-Frame-Options', 'SAMEORIGIN'); - } elseif ($response instanceof \Symfony\Component\HttpFoundation\Response) { - $response->headers->set('X-Frame-Options', 'SAMEORIGIN'); - } - } - - return $response; - } -} diff --git a/app/Http/Resources/FormSubmissionResource.php b/app/Http/Resources/FormSubmissionResource.php index 6018e9e..ad2b932 100644 --- a/app/Http/Resources/FormSubmissionResource.php +++ b/app/Http/Resources/FormSubmissionResource.php @@ -50,7 +50,11 @@ class FormSubmissionResource extends JsonResource return $file !== null && $file; })->map(function ($file) { return [ - 'file_url' => route('open.forms.submissions.file', [$this->form_id, $file]), + 'file_url' => \URL::signedRoute( + 'open.forms.submissions.file', + [$this->form_id, $file], + now()->addMinutes(10) + ), 'file_name' => $file, ]; }); diff --git a/app/Jobs/Form/StoreFormSubmissionJob.php b/app/Jobs/Form/StoreFormSubmissionJob.php index 8361f04..198bb2c 100644 --- a/app/Jobs/Form/StoreFormSubmissionJob.php +++ b/app/Jobs/Form/StoreFormSubmissionJob.php @@ -164,14 +164,14 @@ class StoreFormSubmissionJob implements ShouldQueue return null; } - if(filter_var($value, FILTER_VALIDATE_URL) !== FALSE && str_contains($value, parse_url(config('app.url'))['host'])) { // In case of prefill we have full url so convert to s3 + if(filter_var($value, FILTER_VALIDATE_URL) !== false && str_contains($value, parse_url(config('app.url'))['host'])) { // In case of prefill we have full url so convert to s3 $fileName = basename($value); $path = FormController::ASSETS_UPLOAD_PATH . '/' . $fileName; $newPath = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $this->form->id); Storage::move($path, $newPath.'/'.$fileName); return $fileName; } - + if($this->isSkipForUpload($value)) { return $value; } diff --git a/app/Models/Forms/Form.php b/app/Models/Forms/Form.php index edfea0d..53c4039 100644 --- a/app/Models/Forms/Form.php +++ b/app/Models/Forms/Form.php @@ -157,12 +157,12 @@ class Form extends Model implements CachableAttributes if ($this->custom_domain) { return 'https://' . $this->custom_domain . '/forms/' . $this->slug; } - return url('/forms/' . $this->slug); + return front_url('/forms/' . $this->slug); } public function getEditUrlAttribute() { - return url('/forms/' . $this->slug . '/show'); + return front_url('/forms/' . $this->slug . '/show'); } public function getSubmissionsCountAttribute() diff --git a/app/Models/Template.php b/app/Models/Template.php index 59c42e3..45fa38f 100644 --- a/app/Models/Template.php +++ b/app/Models/Template.php @@ -48,7 +48,7 @@ class Template extends Model public function getShareUrlAttribute() { - return url('/form-templates/'.$this->slug); + return front_url('/form-templates/'.$this->slug); } public function setDescriptionAttribute($value) diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 9edd12f..5260531 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -17,7 +17,7 @@ class ResetPassword extends Notification { return (new MailMessage) ->line('You are receiving this email because we received a password reset request for your account.') - ->action('Reset Password', url('password/reset/'.$this->token).'?email='.urlencode($notifiable->email)) + ->action('Reset Password', front_url('password/reset/'.$this->token).'?email='.urlencode($notifiable->email)) ->line('If you did not request a password reset, no further action is required.'); } } diff --git a/app/Notifications/Subscription/FailedPaymentNotification.php b/app/Notifications/Subscription/FailedPaymentNotification.php index f50a93f..dcb3970 100644 --- a/app/Notifications/Subscription/FailedPaymentNotification.php +++ b/app/Notifications/Subscription/FailedPaymentNotification.php @@ -36,6 +36,6 @@ class FailedPaymentNotification extends Notification implements ShouldQueue ->line(__('Please go to OpenForm, click on your name on the top right corner, and click on "Billing". You will then be able to update your card details. To avoid any service disruption, you can reply to this email whenever you updated your card details, and we\'ll manually attempt to charge your card.')) - ->action(__('Go to OpenForm'), url('/')); + ->action(__('Go to OpenForm'), front_url('/')); } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index faee4fa..989bcff 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -19,15 +19,6 @@ class RouteServiceProvider extends ServiceProvider */ public const HOME = '/home'; - /** - * The controller namespace for the application. - * - * When present, controller route declarations will automatically be prefixed with this namespace. - * - * @var string|null - */ - // protected $namespace = 'App\\Http\\Controllers'; - /** * Define your route model bindings, pattern filters, etc. * @@ -39,19 +30,9 @@ class RouteServiceProvider extends ServiceProvider $this->registerGlobalRouteParamConstraints(); $this->routes(function () { - - Route::prefix('api') - ->middleware('api') + Route::middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); - - Route::middleware('web') - ->namespace($this->namespace) - ->group(base_path('routes/web.php')); - - Route::middleware('spa') - ->namespace($this->namespace) - ->group(base_path('routes/spa.php')); }); } diff --git a/app/Service/Forms/Webhooks/DiscordHandler.php b/app/Service/Forms/Webhooks/DiscordHandler.php index 559de29..f7529f5 100644 --- a/app/Service/Forms/Webhooks/DiscordHandler.php +++ b/app/Service/Forms/Webhooks/DiscordHandler.php @@ -27,7 +27,7 @@ class DiscordHandler extends AbstractWebhookHandler $externalLinks[] = '[**🔗 Open Form**](' . $this->form->share_url . ')'; } if(Arr::get($settings, 'link_edit_form', true)){ - $editFormURL = url('forms/' . $this->form->slug . '/show'); + $editFormURL = front_url('forms/' . $this->form->slug . '/show'); $externalLinks[] = '[**✍️ Edit Form**](' . $editFormURL . ')'; } if (Arr::get($settings, 'link_edit_submission', true) && $this->form->editable_submissions) { diff --git a/app/Service/Forms/Webhooks/SlackHandler.php b/app/Service/Forms/Webhooks/SlackHandler.php index 5b2faf6..f237efa 100644 --- a/app/Service/Forms/Webhooks/SlackHandler.php +++ b/app/Service/Forms/Webhooks/SlackHandler.php @@ -27,7 +27,7 @@ class SlackHandler extends AbstractWebhookHandler $externalLinks[] = '*<' . $this->form->share_url . '|🔗 Open Form>*'; } if(Arr::get($settings, 'link_edit_form', true)){ - $editFormURL = url('forms/' . $this->form->slug . '/show'); + $editFormURL = front_url('forms/' . $this->form->slug . '/show'); $externalLinks[] = '*<' . $editFormURL . '|✍️ Edit Form>*'; } if (Arr::get($settings, 'link_edit_submission', true) && $this->form->editable_submissions) { diff --git a/app/helpers.php b/app/helpers.php new file mode 100644 index 0000000..e287b47 --- /dev/null +++ b/app/helpers.php @@ -0,0 +1,11 @@ + +
+ + + + + + + + + + + + +
+ + + diff --git a/client/components/forms/CheckboxInput.vue b/client/components/forms/CheckboxInput.vue new file mode 100644 index 0000000..fa37fd4 --- /dev/null +++ b/client/components/forms/CheckboxInput.vue @@ -0,0 +1,46 @@ + + + diff --git a/client/components/forms/CodeInput.client.vue b/client/components/forms/CodeInput.client.vue new file mode 100644 index 0000000..e276856 --- /dev/null +++ b/client/components/forms/CodeInput.client.vue @@ -0,0 +1,63 @@ + + + diff --git a/client/components/forms/ColorInput.vue b/client/components/forms/ColorInput.vue new file mode 100644 index 0000000..3bfa0e8 --- /dev/null +++ b/client/components/forms/ColorInput.vue @@ -0,0 +1,45 @@ + + + diff --git a/client/components/forms/DateInput.vue b/client/components/forms/DateInput.vue new file mode 100644 index 0000000..44afd99 --- /dev/null +++ b/client/components/forms/DateInput.vue @@ -0,0 +1,187 @@ + + + diff --git a/resources/js/components/forms/FileInput.vue b/client/components/forms/FileInput.vue similarity index 82% rename from resources/js/components/forms/FileInput.vue rename to client/components/forms/FileInput.vue index 0b041e6..4d904dc 100644 --- a/resources/js/components/forms/FileInput.vue +++ b/client/components/forms/FileInput.vue @@ -1,21 +1,10 @@ - - - - - + + + diff --git a/resources/js/components/forms/ScaleInput.vue b/client/components/forms/ScaleInput.vue similarity index 68% rename from resources/js/components/forms/ScaleInput.vue rename to client/components/forms/ScaleInput.vue index ea162cf..5eef878 100644 --- a/resources/js/components/forms/ScaleInput.vue +++ b/client/components/forms/ScaleInput.vue @@ -1,14 +1,10 @@ \ No newline at end of file + diff --git a/client/components/forms/SignatureInput.vue b/client/components/forms/SignatureInput.vue new file mode 100644 index 0000000..3859127 --- /dev/null +++ b/client/components/forms/SignatureInput.vue @@ -0,0 +1,62 @@ + + + diff --git a/client/components/forms/TextAreaInput.vue b/client/components/forms/TextAreaInput.vue new file mode 100644 index 0000000..6929602 --- /dev/null +++ b/client/components/forms/TextAreaInput.vue @@ -0,0 +1,56 @@ +