Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standalone React and Headless Rails applications #6287

Merged
merged 173 commits into from
Aug 10, 2023
Merged

Conversation

purfectliterature
Copy link
Contributor

@purfectliterature purfectliterature commented Jul 19, 2023

This PR splits Coursemology into two apps: a standalone React app and headless Rails app. Both apps are independent of each other and must be bootstrapped on different processes. The default HTML entry point to the app is now the standalone React app.

Note

At this stage, we cannot afford to make the Rails app API-only. Cookies (and cookie-based sessions), CSRF protection, and more are not available by default in an API-only Rails app. Manual extensions and tests will need to be done to go API-only.

Development changes

  • Use lvh.me to access the app. This enables multi-tenancy on local environments.
    Run host lvh.me on your Terminal to bind localhost and 127.0.0.1 to lvh.me. Then, access the React app on lvh.me:8080 and the Rails app on lvh.me:5000 (or your set ports). You can now develop on other instances, e.g., nushigh.lvh.me.
  • CORS is now enforced on the Rails app.
  • webpack-dev-server now acts as a reverse proxy to the Rails app.
    It proxies requests with ?format=json and rewrites the Origin header to please CORS. See the devServer key on webpack.dev.js for more information.
  • Foreman is now deprecated.
    Bootstrap both React and Rails app on separate processes. This also makes it way easier to use Byebug since Foreman cannot show standard inputs.
  • Capybara tests are deprecated. Write new end-to-end tests with Playwright.
    Existing Capybara tests still work, and can be updated or extended if needed as we discover edge cases or bug fixes. But new tests should be written with Playwright.
  • yarn build:test now sets BABEL_ENV to something else than production.
    This is done to ensure data-testid attributes are not removed during webpack's production build.
  • Add a new .env in client if you haven't already. Then add this entry for reCAPTCHA.
    This is the same testing key as the one in the Rails app. If the site key in Rails app changes, make sure you update this too.
GOOGLE_RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI

Important

We'd probably need to rewrite our Getting Started guide at some point. Maybe sometime after we set up our repo for the Go server.

Note

Playwright tests currently live in tests/tests. The idea is to have ALL end-to-end tests under tests. Then we can have tests/playwright and tests/capybara, for example, and bootstrap them with appropriate scripts in tests/package.json. I'm not sure if we can strip out Capybara tests from the Rails app, though.

We're going to move some files and folders around once we start writing some Go codes, anyway. So, I envision the root of the repo will have folders like: client, api-v1, api-v2, tests, and any other environments/configs/CI files. We can have one script (maybe package.json) containing all the configs (environment variables, ports, etc.) at the root of the project.

CircleCI pipeline changes

  • Add build_client job to build and cache client.
  • Add test_playwright job for Playwright tests.
  • Node jobs build_client, test_playwright, jslint, and jstest now use CircleCI's Node convenience image.
  • jslint and jstest now don't build client since it's unnecessary.
  • Yarn cache now also caches vendor/recorderjs/node_modules.
  • Split i18n to i18n_en and i18n_zh. i18n_en is now required for merging to master.
  • test is now test_rspec.
  • lint is now factorybot_lint.
  • Renamed some commands to be more descriptive.

Note

After this PR is merged, we need to remove ci/circleci: test and ci/circleci: lint from master's branch protection settings. Until then, ignore the pending results for lint and test in below status checks.

Notable changes

  • 🔥 The client is now a fully standalone React app.
    Webpack injects the bundled JavaScript scripts with HtmlWebpackPlugin. index.tsx now immediately binds ReactDOM on script load.
  • 🔥 New authentication pages.
    Sign in, Sign out, Forgot password, Reset password, and Resend confirmation email pages.
  • 🔥 New Terms of Service and Privacy Policy pages.
    These pages are code-split. The contents of these pages are rendered in Markdown. There's a new component, MarkdownPage.
  • 🔥 Site-wide user options are now split from course user options as an avatar button beside the app logo.
  • 🔥 The client app is now split to UnauthenticatedApp and AuthenticatedApp.
    They are code-split.
  • 🔥 ScribingViewComponent now lazy loads its fabric- and react-color-dependent children.
    They are code-split.
  • 🔥 We now have a preflight, CssBaseline.
    Some components and pages that were using bare HTML elements, e.g., h4, span, etc., were converted to their appropriate counterparts with Typography.
  • 🔥 react-toastify and NotificationPopup toasts' styles are now standardised.
  • 🔥 / when authenticated now routes to a dashboard page: list of courses with and sorted by last accessed times.
    If the user has only one course, it will automatically redirect to that course. If the user has no courses, it will automatically redirect to /courses.
  • 🔥 Add new session store that stores i18n config and authentication state.
    This is intended to be extended further in the future to include authentication details, permissions, actual session IDs, etc., if needed.
  • 🔥 The base Axios client now supports CSRF recycling.
    Before making any non-GET requests, it will request a fresh CSRF token and cache it if not already, expired, or invalid. It will continue requesting GET to /csrf_token until the non-GET request gets through, for a maximum of 3 times.
  • 🔥 The base Axios client now redirects 401 and CanCan::AccessDenied 403 to the Sign In and Forbidden pages.
  • 🔥 "Attempt" and "Watch" buttons in assessments and videos now directly links to their /attempt URLs.
    This way, there's no need for manually GET-ting to /attempt and redirect programmatically. This also allows users to Open Link in New Tab on these buttons.
  • 🔨 In addition to the React component stack, ErrorBoundary now also prints out the raw Error stack.
  • 🔨 Deprecate lib/server-context.js.
    There's no need to infer Rails controller name in React. I18n config and CSRF token are managed by I18nProvider and the base Axios client, respectively.
  • 🔨 Deprecate lib/axios.js.
  • 🔨 Footer now appears on short screens on course pages.
  • 🔨 Page now renders a Fragment to reduce extra div nesting.
  • 🔨 PopupMenuButton now supports a secondary title/component.
  • 🔨 Accordion now supports a custom icon component.
  • 🔨 Capybara: Add expect_forbidden matcher.
  • 🔨 Capybara: Add new login_as and logout performers (supersedes Warden's).
  • 🔨 Move sass, dotenv-webpack, glob, and mkdirp to devDependencies.
  • 🐛 Fix clear button focusable in SearchFields.
  • 🐛 Fix custom onKeyDown function is not invocable in TextFields.
  • 🐛 Fix TypeError when loading UserEmailSubscriptions page.
  • 🐛 Fix CoursesIndex not opening New Course dialog when ?new=true when loading.

For full changelog, refer to the commit history.

Deployment changes

  • coursemology-theme can now be safely set as read-only and archived. There's nothing there that is longer relevant to our app.
  • dockerfiles may still contain some production-related files and configurations. We'll have to eventually move them here.
  • Rewrites must be set for /static/*, /*, and ?format=json to rewrite them to the static files, /index.html, and the Rails server, respectively.
  • CORS configurations and multi-tenancy access for production might still need some manual testing.

@purfectliterature purfectliterature self-assigned this Jul 19, 2023
@purfectliterature purfectliterature changed the title Standalone React application, Headless Rails server Standalone React and Headless Rails applications Jul 20, 2023
@purfectliterature purfectliterature force-pushed the phillmont/spa-letsgo branch 11 times, most recently from c5dc21a to b5c9690 Compare July 25, 2023 06:21
@purfectliterature purfectliterature force-pushed the phillmont/spa-letsgo branch 5 times, most recently from 3a3125e to d270e32 Compare August 1, 2023 03:21
@purfectliterature purfectliterature added Enhancement Technical Story Feature UI Ruby Pull requests that update Ruby code JavaScript Pull requests that update JavaScript code labels Aug 1, 2023
@purfectliterature purfectliterature force-pushed the phillmont/spa-letsgo branch 6 times, most recently from 3aca1c3 to 9e0489e Compare August 1, 2023 09:42
purfectliterature and others added 26 commits August 10, 2023 08:55
Relevant means if there are >1 enrolled courses or not in CoursesIndex.
If in CoursesIndex and there are no enrolled courses, do not show the
Courses button.
@ekowidianto ekowidianto force-pushed the phillmont/spa-letsgo branch from 0d1feca to 9263d5d Compare August 10, 2023 00:58
@ekowidianto ekowidianto merged commit e8b4c64 into master Aug 10, 2023
@ekowidianto ekowidianto deleted the phillmont/spa-letsgo branch August 10, 2023 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Feature JavaScript Pull requests that update JavaScript code Ruby Pull requests that update Ruby code Technical Story UI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants