From 1f873979f3a748412cd5851f5d330b4f08419f2a Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 29 Dec 2020 13:13:48 +0100 Subject: [PATCH] architecture documentation --- CHANGELOG.md | 1 + Procfile | 2 +- Rakefile | 2 + .../src/javascript/filters/filters.js | 10 +- config.ru | 4 +- doc/README.md | 3 + doc/architecture.md | 115 ++++++++++++++++++ 7 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 doc/architecture.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c40518921..4e3baefbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Next release - Refactored theme builder to use scss files - Updated stripe gem to 5.21.0 +- Architecture documentation - Fix a bug: unable to access embedded plan views - Fix a bug: warning message overflow in credit wallet modal - Fix a bug: when using a cash coupon, the amount shown in the statistics is invalid diff --git a/Procfile b/Procfile index e68a73938..bbda6f44f 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,4 @@ -web: bundle exec rails server puma -p $PORT +#web: bundle exec rails server puma -p $PORT worker: bundle exec sidekiq -C ./config/sidekiq.yml wp-client: bin/webpack-dev-server wp-server: SERVER_BUNDLE_ONLY=yes bin/webpack --watch diff --git a/Rakefile b/Rakefile index e85f91391..488c551fe 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/app/frontend/src/javascript/filters/filters.js b/app/frontend/src/javascript/filters/filters.js index 8c808901d..e6cb02e7c 100644 --- a/app/frontend/src/javascript/filters/filters.js +++ b/app/frontend/src/javascript/filters/filters.js @@ -45,7 +45,7 @@ Application.Filters.filter('machineFilter', [function () { }; }]); -Application.Filters.filter('projectMemberFilter', [ 'Auth', function (Auth) { +Application.Filters.filter('projectMemberFilter', ['Auth', function (Auth) { return function (projects, selectedMember) { if (!angular.isUndefined(projects) && angular.isDefined(selectedMember) && (projects != null) && (selectedMember != null) && (selectedMember !== '')) { const filteredProject = []; @@ -165,7 +165,7 @@ Application.Filters.filter('simpleText', [function () { }; }]); -Application.Filters.filter('toTrusted', [ '$sce', function ($sce) { +Application.Filters.filter('toTrusted', ['$sce', function ($sce) { return text => $sce.trustAsHtml(text); }]); @@ -178,7 +178,7 @@ Application.Filters.filter('humanReadablePlanName', ['$filter', function ($filte if (plan != null) { let result = plan.base_name; if (groups != null) { - for (let group of Array.from(groups)) { + for (const group of Array.from(groups)) { if (group.id === plan.group_id) { if (short != null) { result += ` - ${group.slug}`; @@ -318,7 +318,7 @@ Application.Filters.filter('toIsoDate', [function () { }; }]); -Application.Filters.filter('booleanFormat', [ '_t', function (_t) { +Application.Filters.filter('booleanFormat', ['_t', function (_t) { return function (boolean) { if (((typeof boolean === 'boolean') && boolean) || ((typeof boolean === 'string') && (boolean === 'true'))) { return _t('app.shared.buttons.yes'); @@ -328,7 +328,7 @@ Application.Filters.filter('booleanFormat', [ '_t', function (_t) { }; }]); -Application.Filters.filter('maxCount', [ '_t', function (_t) { +Application.Filters.filter('maxCount', ['_t', function (_t) { return function (max) { if ((typeof max === 'undefined') || (max === null) || ((typeof max === 'number') && (max === 0))) { return _t('app.admin.pricing.unlimited'); diff --git a/config.ru b/config.ru index 5bc2a619e..61c04e13f 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require ::File.expand_path('../config/environment', __FILE__) run Rails.application diff --git a/doc/README.md b/doc/README.md index 0193418b7..d4f4098d0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -32,6 +32,9 @@ If you intend to translate Fab-manager to a new, or an already supported languag ### Developer's documentation The following guides should help those who want to contribute to the code. +#### Architecture +- [Code architecture](architecture.md) + #### How to setup a development environment - [With docker-compose](development_readme.md) diff --git a/doc/architecture.md b/doc/architecture.md new file mode 100644 index 000000000..0c763c7c7 --- /dev/null +++ b/doc/architecture.md @@ -0,0 +1,115 @@ +# Architecture + +## Root + +`fab-manager/` +╠═ `.docker/` In development, data of the databases are stored in this untracked folder; +╠═ `.github/` Configuration of the GitHub repository; +╠═ `accounting/` When some accounting exports are generated in the application, they are saved in this untracked folder; +╠═ `app/` **The source code of the application**; +╠═ `bin/` Ruby-on-rails binaries; +╠═ `config/` Application and frameworks configurations are saved here. **Translations are saved here too**; +╠═ `coverage/` Coveralls.io saves its temporary data into this untracked folder; +╠═ `db/` Database schema and migrations (ie. the history of the construction of the database); +╠═ `doc/` Various documentations about Fab-manager; +╠═ `docker/` Files used to build the docker image. Also: files to set up a development environment based on docker; +╠═ `exports/` When some exports are generated in the application, they are saved in this untracked folder; +╠═ `imports/` When some files are imported to the application, they are saved in this untracked folder; +╠═ `invoices/` When some invoices are generated in the application, they are saved in this untracked folder; +╠═ `lib/` **Some more code of the application**. This code may not be loaded automatically; +╠═ `log/` When running, the application will produce some debug outputs, they are saved in this untracked folder; +╠═ `node_modules` Third party libraries for the front-end JS application are stored in this untracked folder by the package manager (yarn); +╠═ `payment_schedules` When some payment schedules are generated in the application, they are saved in this untracked folder; +╠═ `plugins/` Some code can be dropped in that untracked folder to use plugins with Fab-manager; +╠═ `provision/` Scripts used to setup a development environment based on vagrant; +╠═ `public` Files that will be exposed to the world by the HTTP server (nginx). This includes the compilation result of the front-end application; +╠═ `scripts/` Some bash scripts. Scripts ran during the upgrade phrase are located here; +╠═ `setup/` Everything needed to set up a new instance of Fab-manager, including the setup script; +╠═ `test/` Automated tests of the application (MiniTest); +╠═ `tmp/` Various temporary files are stored in this untracked folder; +╠═ `vendor/` (deprecated) Previously 3rd-party assets were stored here. Now, only the fonts for the PDF generation remains here; +╠═ `.browserslistrc` Required by babel (JS compiler) to specify target browsers for the compilation of the front-end application; +╠═ `.coveralls.yml` Configuration of coveralls.io; +╠═ `.dockerignore` List of files that won't be included in the docker image; +╠═ `.env` Environment variables for development and test environments; +╠═ `.eslitignore` List of files that won't be parsed by ESLint; +╠═ `.eslintrc` Configuration of the JS code quality checking (ESLint); +╠═ `.gemrc` Ruby gems configuration; +╠═ `.gitignore` List of files that won't be tracked by the version control system (git); +╠═ `.nvmrc` Version of node.js used in this project. This file is read by NVM in development environments; +╠═ `.rubocop.yml` Configuration of the Ruby code quality checking (Rubocop); +╠═ `.ruby-gemset` Used by RVM to isolate the gems of this application +╠═ `.ruby-version` Version of Ruby used in this project. This file is read by RVM in development environments; +╠═ `babel.config.js` Configuration of babel (JS compiler); +╠═ `Capfile` (deprecated) Configuration of capistrano (previous deployment system); +╠═ `CHANGELOG.md` List of changes between releases of Fab-manager. Also contains deployment instructions for upgrading; +╠═ `config.ru` This file is used by Rack-based servers to start the application; +╠═ `CONTRIBUTING.md` Contribution guidelines; +╠═ `crowdin.yml` Configuration of the translation management system (Crowdin); +╠═ `Dockerfile` This file list instructions to build the docker image of the application; +╠═ `env.example` Example of configuration for the environment variables, for development and test environments; +╠═ `Gemfile` List of third-party libraries used in the Ruby-on-Rails application; +╠═ `Gemfile.lock` Version lock of the ruby-on-rails dependencies; +╠═ `LICENSE.md` Publication licence of Fab-manager; +╠═ `package.json` List of third-party libraries used in the Javascript application. Also: version number of Fab-manager; +╠═ `postcss.config.js` Configuration of PostCSS (CSS compiler); +╠═ `Procfile` List the process ran by foreman when starting the application in development; +╠═ `Rakefile` Configuration of Rake (Ruby commands interpreter); +╠═ `README.md` Entrypoint for the documentation; +╠═ `tsconfig.json` Configuration of TypeScript; +╠═ `Vagrantfile` Configuration of Vagrant, for development environments; +╠═ `yarn.lock` Version lock of the javascript dependencies; +╚═ `yarn-error.log` This untracked file keeps logs of the package manager (yarn), if any error occurs; + +## Backend application + +The backend application respects the Ruby-on-Rails conventions for MVC applications. +It mainly provides a REST-JSON API for the frontend application. +It also provides another REST-JSON API, open to the 3rd-party applications, and known as OpenAPI. + +`fab-manager/` +╚═╦ `app/` + ╠═ `controllers/` Controllers (MVC); + ╠═ `doc/` Documentation for the OpenAPI; + ╠═ `exceptions/` Custom errors; + ╠═ `frontend/` **Source code for the frontend application**; + ╠═ `helpers/` System-wide libraries and utilities. Prefer using `services/` when it's possible; + ╠═ `mailers/` Sending emails; + ╠═ `models/` Models (MVC); + ╠═ `pdfs/` PDF documents generation; + ╠═ `policies/` Access policies for the API and OpenAPI endpoints; + ╠═ `services/` Utilities arranged by data models; + ╠═ `sweepers/` Build cached version of some data; + ╠═ `themes/` SASS files that overrides the frontend styles. We plan to move all styles here to build multiple themes; + ╠═ `uploaders/` Handling of the uploaded files + ╠═ `validators/` Custom data validation (before saving); + ╠═ `views/` Views (MVC) + ╚═ `workers/` Asynchronous tasks run by Sidekiq + +## Frontend application + +The frontend application is historically an Angular.js MVC application. +We are moving, step-by-step, to an application based on React.js + Typescript. +For now, the main application is still using Angular.js but it uses some React.js components thanks to coatue-oss/react2angular. + +`fab-manager/` +╚═╦ `app/` + ╚═╦ `frontend/` + ╠═ `images/` Static images used all over the frontend app; + ╠═ `packs/` Entry points for webpack (bundler); + ╠═╦ `src/` + ║ ╠═╦ `javascript/` + ║ ║ ╠═ `api/` (TS) New components to access the backend API; + ║ ║ ╠═ `components/` (TS) New React.js components; + ║ ║ ╠═ `controllers/` (JS) Old Angular.js controllers for the views located in `app/frontend/templates`; + ║ ║ ╠═ `directives/` (JS) Old Angular.js directives (interface components); + ║ ║ ╠═ `filters/` (JS) Old Angular.js filters (processors transforming data); + ║ ║ ╠═ `lib/` (TS) New utilities + (JS) Old external libraries customized; + ║ ║ ╠═ `models/` (TS) Typed interfaces reflecting the API data models; + ║ ║ ╠═ `services/` (JS) Old Angular.js components to access the backend API; + ║ ║ ╠═ `typings/` (TS) Typed modules for non-JS/TS file types; + ║ ║ ╠═ `app.js` Entrypoint for the angular.js application; + ║ ║ ╠═ `plugins.js.erb` Entrypoint for embedding Fab-manager's plugins in the frontend application; + ║ ║ ╚═ `router.js` Configuration for UI-Router (mapping between routes, controllers and templates) + ║ ╚═ `stylesheets/` SASS source for the application style + ╚═ `templates/` Angular.js views (HTML)