Skip to content

Commit

Permalink
Migrate front-end to Nuxt app (#284)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* 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 <[email protected]>
Co-authored-by: Julien Nahum <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* Tiny fixes + start pre-rendering

* migrate-to-nuxt-useappconfig (#263)

* migrate-to-nuxt-useappconfig

* defineAppConfig

---------

Co-authored-by: Forms Dev <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* nuxt migration -file upload - WIP (#271)

Co-authored-by: Julien Nahum <[email protected]>

* 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 <[email protected]>
Co-authored-by: Chirag Chhatrala <[email protected]>
Co-authored-by: Rishi Raj Jain <[email protected]>
Co-authored-by: formsdev <[email protected]>
  • Loading branch information
5 people authored Jan 15, 2024
1 parent c01f566 commit 0adce5a
Show file tree
Hide file tree
Showing 478 changed files with 27,683 additions and 34,127 deletions.
16 changes: 0 additions & 16 deletions .eslintrc.js

This file was deleted.

32 changes: 25 additions & 7 deletions .github/workflows/laravel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -154,8 +154,11 @@ First, let's work with the codebase and its dependencies.
# Get the code!
git clone [email protected]: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
Expand Down Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions amplify.yml
Original file line number Diff line number Diff line change
@@ -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/**/*
2 changes: 1 addition & 1 deletion app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected function unauthenticated($request, AuthenticationException $exception)
{
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(url('/login'));
: redirect(front_url('login'));
}

public function report(Throwable $exception)
Expand Down
8 changes: 4 additions & 4 deletions app/Http/Controllers/Auth/AppSumoAuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ public function handleCallback(Request $request)

// 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
Expand Down Expand Up @@ -82,11 +82,11 @@ private function attachLicense(License $license) {
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'));
}

/**
Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/Content/FileUploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
12 changes: 7 additions & 5 deletions app/Http/Controllers/Forms/FormSubmissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -51,9 +52,6 @@ public function export(string $id)

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);

Expand All @@ -63,8 +61,12 @@ public function submissionFile($id, $fileName)
], 404);
}

if (config('filesystems.default') !== 's3') {
return response()->file(Storage::path($fileName));
}

return redirect(
Storage::temporaryUrl($fileName, now()->addMinute())
Storage::temporaryUrl($fileName, now()->addMinute())
);
}
}
60 changes: 11 additions & 49 deletions app/Http/Controllers/SitemapController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,62 +9,24 @@

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;
}
}
18 changes: 0 additions & 18 deletions app/Http/Controllers/SpaController.php

This file was deleted.

4 changes: 2 additions & 2 deletions app/Http/Controllers/SubscriptionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public function checkout($pricing, $plan, $trial = null)
$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',
Expand Down
9 changes: 3 additions & 6 deletions app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

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;
Expand All @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Middleware/Authenticate.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Authenticate extends Middleware
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return redirect('/login');
return redirect(front_url('login'));
}
}
}
8 changes: 8 additions & 0 deletions app/Http/Middleware/AuthenticateJWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

class AuthenticateJWT
{
const API_SERVER_SECRET_HEADER_NAME = 'x-api-secret';

/**
* Verifies the JWT token and validates the IP and User Agent
Expand All @@ -24,6 +25,13 @@ public function handle(Request $request, Closure $next)

// 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';
Expand Down
8 changes: 5 additions & 3 deletions app/Http/Middleware/CustomDomainRestriction.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class CustomDomainRestriction
{
const CUSTOM_DOMAIN_HEADER = "User-Custom-Domain";
const CUSTOM_DOMAIN_HEADER = "x-custom-domain";

/**
* Handle an incoming request.
Expand All @@ -27,7 +27,8 @@ public function handle(Request $request, Closure $next)
return response()->json([
'success' => false,
'message' => 'Invalid domain',
], 400);
'error' => 'invalid_domain',
], 420);
}

// Check if domain is different from current domain
Expand All @@ -41,7 +42,8 @@ public function handle(Request $request, Closure $next)
return response()->json([
'success' => false,
'message' => 'Unknown domain',
], 400);
'error' => 'invalid_domain',
], 420);
}

Workspace::addGlobalScope('domain-restricted', function (Builder $builder) use ($workspace) {
Expand Down
Loading

0 comments on commit 0adce5a

Please sign in to comment.