diff --git a/.gitignore b/.gitignore index cc191ab98..7d13ee199 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,9 @@ .tags* .tmp -.env -source/data -node_modules/ -dist/ .DS_Store -package-lock.json yarn-error.log -cypress/videos -cypress/screenshots +package-lock.json +node_modules/ + +# Local Netlify folder +.netlify \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b72f60dd6..1f93d56cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,12 +39,21 @@ git clone --depth 100 git@github.com:betagouv/mon-entreprise.git && cd mon-entre # Install the Javascript dependencies through Yarn yarn install -# Run the server +# Run the server for mon-entreprise +cd mon-entreprise yarn start ``` L'application est exécuté sur https://localhost:8080/mon-entreprise pour la version française et http://localhost:8080/infrance pour la version anglaise. +Si vous souhaitez travailler sur le package publicode, on peut créer un lien +symbolique depuis mon-entreprise en executant la commande suivante à la racine +du projet : + +``` +yarn run link:publicodes +``` + ### Messages de commit A mettre sans retenue dans les messages de commit : @@ -90,7 +99,7 @@ Si vous souhaitez mettre à jour les snapshots vous pouvez utiliser le paramètr Enfin pour les tests d'intégration : ```sh -$ yarn run test-cypress +$ yarn run cypress run ``` ### Traduction 👽 @@ -121,7 +130,7 @@ $ yarn run i18n:rules:translate $ yarn run i18n:ui:translate ``` -N'oubliez pas de vérifier le diff que rien n'est choquant. +N'oubliez pas de vérifier sur le diff que rien n'est choquant. ### CI/CD @@ -132,7 +141,7 @@ N'oubliez pas de vérifier le diff que rien n'est choquant. ### Analyse des bundles -La commande `yarn run analyze-bundle` gènere une visualisation interactive du +La commande `yarn run compile:analyse-bundle` gènere une visualisation interactive du contenu packagé, cf. [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) @@ -148,7 +157,7 @@ raisonnement ayant abouti à ce langage sont dispos sur le repository ailleurs inutilisé. Pour se familiariser avec les règles, vous pouvez jeter un œil aux fichiers -contenant les règles elles-mêmes (dans le dossier `source/rules`) mais cela peut +contenant les règles elles-mêmes (dans le dossier `rules`) mais cela peut s'avérer assez abrupt. Essayez plutôt de jeter un oeil [aux tests](./test/mécanismes/expressions.yaml) diff --git a/README.md b/README.md index 5602f1a76..b56b72540 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This repository powers [mycompanyinfrance.fr](https://mycompanyinfrance.fr) and [mon-entreprise.fr](https://mon-entreprise.fr) and [publi.codes](https://publi.codes). -The hiring simulator, available on both websites, embeds a [model](https://github.com/betagouv/mon-entreprise/blob/master/source/rules) of the french tax system as a YAML domain specific language. It enables displaying the computing rules on the Web and having a single source of logic for both the computation engine (a JS library) and the generated end-user conversation-like form. +The hiring simulator, available on both websites, embeds a [model](https://github.com/betagouv/mon-entreprise/blob/master/mon-entreprise/source/rules) of the french tax system as a YAML domain specific language. It enables displaying the computing rules on the Web and having a single source of logic for both the computation engine (a JS library) and the generated end-user conversation-like form. The engine with the French tax law is available as a NPM module and explained [on the wiki](https://github.com/betagouv/mon-entreprise/wiki/Librairie-de-calcul). diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 1ea088270..000000000 --- a/babel.config.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - targets: { - node: 'current' - } - } - ], - '@babel/react', - '@babel/preset-typescript' - ], - plugins: [ - '@babel/plugin-proposal-class-properties', - '@babel/plugin-proposal-optional-chaining', - '@babel/plugin-proposal-nullish-coalescing-operator', - '@babel/plugin-proposal-object-rest-spread', - '@babel/plugin-syntax-dynamic-import', - 'react-hot-loader/babel', - ['webpack-alias', { config: './source/webpack.dev.js' }], - [ - 'ramda', - { - useES: true - } - ], - 'babel-plugin-styled-components' - ] -} diff --git a/babel.config.json b/babel.config.json new file mode 100644 index 000000000..7f64cf41b --- /dev/null +++ b/babel.config.json @@ -0,0 +1,23 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "current" + } + } + ], + "@babel/preset-react", + "@babel/preset-typescript" + ], + "plugins": [ + "babel-plugin-styled-components", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-optional-chaining", + "@babel/plugin-proposal-nullish-coalescing-operator", + "@babel/plugin-proposal-object-rest-spread", + "@babel/plugin-syntax-dynamic-import", + ["ramda", { "useES": true }] + ] +} diff --git a/circle.yml b/circle.yml index fe22e128d..b6a70b9e8 100644 --- a/circle.yml +++ b/circle.yml @@ -5,12 +5,12 @@ commands: - checkout - restore_cache: keys: - - v1-deps-{{ .Branch }}-{{ checksum "package.json" }} + - v1-deps-{{ .Branch }}-{{ checksum "yarn.lock" }} - v1-deps-{{ .Branch }} - v1-deps - run: yarn install --frozen-lockfile - save_cache: - key: v1-deps-{{ .Branch }}-{{ checksum "package.json" }} + key: v1-deps-{{ .Branch }}-{{ checksum "yarn.lock" }} paths: - ~/.cache cypress: @@ -27,7 +27,9 @@ commands: type: string default: https://mon-entreprise.fr steps: - - run: CYPRESS_baseUrl=<< parameters.base_url >> yarn run cypress run --record --key 21660df5-36a5-4c49-b23d-801799b0c759 --env language=<< parameters.language >> --config integrationFolder=cypress/integration/<< parameters.integration_folder >> + - run: | + cd mon-entreprise + CYPRESS_baseUrl=<< parameters.base_url >> yarn run cypress run --record --key 21660df5-36a5-4c49-b23d-801799b0c759 --env language=<< parameters.language >> --config integrationFolder=cypress/integration/<< parameters.integration_folder >> jobs: lint: @@ -36,42 +38,45 @@ jobs: steps: - install - run: | - yarn eslintrc-check - yarn eslint-check --quiet - yarn prettier-check + yarn lint:eslintrc + yarn lint:eslint --quiet + yarn lint:prettier type-check: docker: - image: node:12.16.1-buster steps: - install - - run: | - yarn type-check + - run: yarn test:type i18n-check: docker: - image: node:12.16.1-buster steps: - install - - run: yarn run i18n:rules:check - - run: yarn run i18n:ui:check + - run: | + cd mon-entreprise + yarn run i18n:rules:check + yarn run i18n:ui:check + unit-test: docker: - image: node:12.16.1-buster steps: - install - - run: | - git config --global core.quotepath false - yarn test - yarn test-regressions + - run: git config --global core.quotepath false + - run: yarn test + - run: yarn test:regressions + end-to-end-test: docker: - image: cypress/base:12.16.1 environment: TERM: xterm + resource_class: medium+ steps: - install - - run: yarn run compile-dev + - run: yarn workspace mon-entreprise compile:dev - run: - command: yarn run serve-dev + command: yarn workspace mon-entreprise serve:dev background: true - cypress: base_url: http://localhost:5000 @@ -81,21 +86,13 @@ jobs: - cypress: base_url: http://localhost:5002 integration_folder: publi.codes - bundlesize-test: - docker: - - image: cypress/base:12.16.1 - environment: - TERM: xterm - steps: - - install - - run: | - yarn run simple-compile - yarn test-bundlesize + production-end-to-end-test: docker: - image: cypress/base:12.16.1 environment: TERM: xterm + resource_class: medium+ parallelism: 3 steps: - install @@ -124,7 +121,6 @@ workflows: - i18n-check - unit-test - end-to-end-test - - bundlesize-test - production-end-to-end-test: filters: branches: diff --git a/jest.config.js b/jest.config.js index 606925661..2e2ed6206 100644 --- a/jest.config.js +++ b/jest.config.js @@ -67,18 +67,11 @@ module.exports = { moduleDirectories: ['node_modules', 'sources'], // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "json", - // "jsx", - // "ts", - // "tsx", - // "node" - // ], + moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'], // A map from regular expressions to module names that allow to stub out resources with a single module moduleNameMapper: { - '\\.css$': '/test/regressions/styleMock.js' + '\\.css$': 'mon-entreprise/test/regressions/styleMock.js' }, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader @@ -115,9 +108,7 @@ module.exports = { // rootDir: null, // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], + // roots: [''], // Allows you to use a custom runner instead of Jest's default test runner // runner: "jest-runner", @@ -141,13 +132,11 @@ module.exports = { // testLocationInResults: false, // The glob patterns Jest uses to detect test files - testMatch: [ - // We have 2 test runners (Mocha and Jest), so we create a custom extension without `.test.js` - // to dissociate the two. - '**/*.jest.js' - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - ], + testMatch: ['**/*.jest.js'], + // [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // testPathIgnorePatterns: [ @@ -173,13 +162,14 @@ module.exports = { transform: { // It's not possible to have 2 piped transformers like in webpack // ie ['jest-transform-nearley', 'babel-jest'], so we removed ES6 module from nearley output. - '\\.ne$': 'jest-transform-nearley', - '\\.yaml$': 'yaml-jest', - '\\.(js|tsx?)$': 'babel-jest' + '\\.ne$': require.resolve('jest-transform-nearley'), + '\\.yaml$': require.resolve('yaml-jest'), + '\\.(js|tsx?)$': require.resolve('babel-jest') }, - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - transformIgnorePatterns: ['/node_modules/(?!ramda).+\\.js$'] + // An array of regexp pattern strings that are matched against all source file + // paths, matched files will skip transformation + transformIgnorePatterns: ['node_modules/(?!ramda|publicodes)/'] // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them // unmockedModulePathPatterns: undefined, diff --git a/mon-entreprise/.babelrc.json b/mon-entreprise/.babelrc.json new file mode 100644 index 000000000..752a387a9 --- /dev/null +++ b/mon-entreprise/.babelrc.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + "react-hot-loader/babel", + ["webpack-alias", { "config": "./webpack.dev.js" }] + ] +} diff --git a/mon-entreprise/.eslintrc.yaml b/mon-entreprise/.eslintrc.yaml new file mode 100644 index 000000000..f0436fe75 --- /dev/null +++ b/mon-entreprise/.eslintrc.yaml @@ -0,0 +1,5 @@ +extends: '../.eslintrc' +overrides: + - files: ['*.test.js', 'cypress/integration/**/*.js'] + env: + mocha: true diff --git a/mon-entreprise/.gitignore b/mon-entreprise/.gitignore new file mode 100644 index 000000000..a54fe0bdd --- /dev/null +++ b/mon-entreprise/.gitignore @@ -0,0 +1,8 @@ +.env +node_modules/ +package-lock.json +yarn-error.log +source/data +dist/ +cypress/videos +cypress/screenshots diff --git a/bundlesize.config.json b/mon-entreprise/bundlesize.config.json similarity index 100% rename from bundlesize.config.json rename to mon-entreprise/bundlesize.config.json diff --git a/cypress.json b/mon-entreprise/cypress.json similarity index 100% rename from cypress.json rename to mon-entreprise/cypress.json diff --git a/cypress/.eslintrc.yaml b/mon-entreprise/cypress/.eslintrc.yaml similarity index 100% rename from cypress/.eslintrc.yaml rename to mon-entreprise/cypress/.eslintrc.yaml diff --git a/cypress/fixtures/example.json b/mon-entreprise/cypress/fixtures/example.json similarity index 100% rename from cypress/fixtures/example.json rename to mon-entreprise/cypress/fixtures/example.json diff --git a/cypress/integration/external/external-integrations.js b/mon-entreprise/cypress/integration/external/external-integrations.js similarity index 100% rename from cypress/integration/external/external-integrations.js rename to mon-entreprise/cypress/integration/external/external-integrations.js diff --git a/cypress/integration/mon-entreprise/covid19.js b/mon-entreprise/cypress/integration/mon-entreprise/covid19.js similarity index 100% rename from cypress/integration/mon-entreprise/covid19.js rename to mon-entreprise/cypress/integration/mon-entreprise/covid19.js diff --git a/cypress/integration/mon-entreprise/gérer.js b/mon-entreprise/cypress/integration/mon-entreprise/gérer.js similarity index 100% rename from cypress/integration/mon-entreprise/gérer.js rename to mon-entreprise/cypress/integration/mon-entreprise/gérer.js diff --git a/cypress/integration/mon-entreprise/iframe.js b/mon-entreprise/cypress/integration/mon-entreprise/iframe.js similarity index 100% rename from cypress/integration/mon-entreprise/iframe.js rename to mon-entreprise/cypress/integration/mon-entreprise/iframe.js diff --git a/cypress/integration/mon-entreprise/landing.js b/mon-entreprise/cypress/integration/mon-entreprise/landing.js similarity index 100% rename from cypress/integration/mon-entreprise/landing.js rename to mon-entreprise/cypress/integration/mon-entreprise/landing.js diff --git a/cypress/integration/mon-entreprise/navigation.js b/mon-entreprise/cypress/integration/mon-entreprise/navigation.js similarity index 100% rename from cypress/integration/mon-entreprise/navigation.js rename to mon-entreprise/cypress/integration/mon-entreprise/navigation.js diff --git a/cypress/integration/mon-entreprise/simulateurs.js b/mon-entreprise/cypress/integration/mon-entreprise/simulateurs.js similarity index 95% rename from cypress/integration/mon-entreprise/simulateurs.js rename to mon-entreprise/cypress/integration/mon-entreprise/simulateurs.js index 1a15d7d2c..2d2e09039 100644 --- a/cypress/integration/mon-entreprise/simulateurs.js +++ b/mon-entreprise/cypress/integration/mon-entreprise/simulateurs.js @@ -14,7 +14,7 @@ describe('Simulateurs', function() { }) it('should display a result when entering a value in any of the currency input', () => { - cy.contains('€ / an').click() + cy.contains('€/an').click() if (['indépendant', 'assimilé-salarié'].includes(simulateur)) { cy.get(chargeInputSelector).type(1000) } @@ -33,7 +33,7 @@ describe('Simulateurs', function() { }) it('should allow to change period', function() { - cy.contains('€ / an').click() + cy.contains('€/an').click() cy.wait(200) cy.get(inputSelector) .first() @@ -42,7 +42,7 @@ describe('Simulateurs', function() { cy.get(chargeInputSelector).type('{selectall}6000') } cy.wait(800) - cy.contains('€ / mois').click() + cy.contains('€/mois').click() cy.get(inputSelector) .first() .invoke('val') @@ -82,11 +82,12 @@ describe('Simulateurs', function() { cy.contains('Passer').click() cy.contains('Passer').click() cy.contains('Début 2020').click() + cy.wait(200) cy.contains('Suivant').click() cy.contains('ACRE') }) it('should not have negative value', () => { - cy.contains('€ / mois').click() + cy.contains('€/mois').click() cy.get(inputSelector) .first() .type('{selectall}5000') @@ -101,7 +102,7 @@ describe('Simulateurs', function() { ) }) -describe.only('Simulateur salarié', () => { +describe('Simulateur salarié', () => { if (!fr) { return } diff --git a/cypress/integration/mon-entreprise/status.js b/mon-entreprise/cypress/integration/mon-entreprise/status.js similarity index 100% rename from cypress/integration/mon-entreprise/status.js rename to mon-entreprise/cypress/integration/mon-entreprise/status.js diff --git a/cypress/integration/publi.codes/index.js b/mon-entreprise/cypress/integration/publi.codes/index.js similarity index 100% rename from cypress/integration/publi.codes/index.js rename to mon-entreprise/cypress/integration/publi.codes/index.js diff --git a/cypress/plugins/index.js b/mon-entreprise/cypress/plugins/index.js similarity index 100% rename from cypress/plugins/index.js rename to mon-entreprise/cypress/plugins/index.js diff --git a/cypress/support/commands.js b/mon-entreprise/cypress/support/commands.js similarity index 100% rename from cypress/support/commands.js rename to mon-entreprise/cypress/support/commands.js diff --git a/cypress/support/index.js b/mon-entreprise/cypress/support/index.js similarity index 100% rename from cypress/support/index.js rename to mon-entreprise/cypress/support/index.js diff --git a/index.html b/mon-entreprise/index.html similarity index 100% rename from index.html rename to mon-entreprise/index.html diff --git a/manifest.webmanifest b/mon-entreprise/manifest.webmanifest similarity index 100% rename from manifest.webmanifest rename to mon-entreprise/manifest.webmanifest diff --git a/mon-entreprise/package.json b/mon-entreprise/package.json new file mode 100644 index 000000000..f06be107c --- /dev/null +++ b/mon-entreprise/package.json @@ -0,0 +1,90 @@ +{ + "name": "mon-entreprise", + "license": "MIT", + "version": "1.2.8", + "description": "Library to compute the french social security contributions. Also a website that explains the calculations, and a generic engine to build cool forms that asks the question needed to compute an objective.", + "repository": { + "type": "git", + "url": "https://github.com/betagouv/mon-entreprise.git", + "directory": "mon-entreprise" + }, + "engines": { + "node": ">=12.16.1" + }, + "browserslist": [ + "> 1% in FR", + "not ie < 11" + ], + "devDependencies": { + "i18next-parser": "https://github.com/i18next/i18next-parser#master" + }, + "dependencies": { + "@babel/runtime": "^7.3.4", + "@rehooks/local-storage": "^2.1.1", + "@sentry/browser": "5.15.5", + "classnames": "^2.2.5", + "color-convert": "^1.9.2", + "core-js": "^3.2.1", + "focus-trap-react": "^3.1.2", + "fuse.js": "5.2.1", + "iframe-resizer": "^4.1.1", + "js-yaml": "^3.13.1", + "moo": "^0.5.0", + "nearley": "^2.19.0", + "publicodes": "file:../publicodes", + "puppeteer": "^2.1.1", + "ramda": "^0.27.0", + "react": "^16.13.1", + "react-color": "^2.14.0", + "react-dom": "npm:@hot-loader/react-dom", + "react-easy-emoji": "^1.2.0", + "react-helmet": "6.0.0-beta", + "react-i18next": "^11.0.0", + "react-loading-skeleton": "^2.0.1", + "react-markdown": "^4.1.0", + "react-monaco-editor": "^0.36.0", + "react-number-format": "^4.3.1", + "react-redux": "^7.0.3", + "react-router-dom": "^5.1.1", + "react-router-hash-link": "^1.2.2", + "react-spring": "=8.0.27", + "react-syntax-highlighter": "^10.1.1", + "react-to-print": "^2.5.1", + "react-transition-group": "^2.2.1", + "recharts": "^1.8.5", + "reduce-reducers": "^1.0.4", + "redux": "^4.0.4", + "redux-sentry-middleware": "^0.1.8", + "redux-thunk": "^2.3.0", + "regenerator-runtime": "^0.13.3", + "reselect": "^4.0.0", + "styled-components": "^5.1.0", + "swr": "^0.1.16", + "whatwg-fetch": "^3.0.0", + "yaml": "^1.9.2" + }, + "scripts": { + "prepare": "node scripts/prepare.js", + "compile": "yarn run compile:prod && yarn run compile:legacy", + "compile:prod": "yarn run webpack --config webpack.prod.js", + "compile:legacy": "yarn run webpack --config webpack.prod.legacyBrowser.js", + "compile:stats": "webpack --config webpack.prod.js --profile --json > stats.json", + "compile:analyze-bundle": "ANALYZE_BUNDLE=1 yarn run compile", + "compile:dev": "FR_SITE='http://localhost:5000${path}' EN_SITE='http://localhost:5001${path}' yarn run compile", + "test": "yarn test:file \"./{,!(node_modules)/**/}!(webpack).test.js\"", + "test:file": "yarn mocha-webpack --webpack-config ../webpack.test.js --require source-map-support/register --include test/componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js", + "test:bundlesize": "bundlesize", + "test:dev-e2e:publicode": "cypress open --browser chromium --config baseUrl=http://localhost:8080/publicodes,integrationFolder=cypress/integration/publi.codes", + "test:dev-e2e:mon-entreprise": "cypress open --browser chromium", + "test:dev-e2e:mycompanyinfrance": "cypress open --browser chromium --config baseUrl=http://localhost:8080/infrance", + "i18n:rules:check": "node scripts/i18n/check-missing-rule-translation.js", + "i18n:rules:translate": "node scripts/i18n/translate-rules.js", + "i18n:ui:check": "yarn run i18next -c scripts/i18n/parser.config.js && node scripts/i18n/check-missing-UI-translation", + "i18n:ui:translate": "rm -rf source/locales/static-analysis-fr.json && yarn run i18next -c script/i18n/parser.config.js && node scripts/i18n/translate-ui.js", + "start": "node source/server.js", + "serve:dev": "yarn run serve:dev:mon-entreprise & yarn run serve:dev:mycompanyinfrance & yarn run serve:dev:publicodes", + "serve:dev:mon-entreprise": "PORT=5000 serve --config serve.mon-entreprise.json --no-clipboard", + "serve:dev:publicodes": "PORT=5002 serve --config serve.publicodes.json --no-clipboard", + "serve:dev:mycompanyinfrance": "PORT=5001 serve --config serve.infrance.json --no-clipboard" + } +} diff --git a/source/scripts/.eslintrc.yaml b/mon-entreprise/scripts/.eslintrc.yaml similarity index 100% rename from source/scripts/.eslintrc.yaml rename to mon-entreprise/scripts/.eslintrc.yaml diff --git a/source/scripts/check-dead-links.js b/mon-entreprise/scripts/check-dead-links.js similarity index 100% rename from source/scripts/check-dead-links.js rename to mon-entreprise/scripts/check-dead-links.js diff --git a/source/scripts/dottednames.js b/mon-entreprise/scripts/dottednames.js similarity index 85% rename from source/scripts/dottednames.js rename to mon-entreprise/scripts/dottednames.js index 9f936a08e..d5d928803 100644 --- a/source/scripts/dottednames.js +++ b/mon-entreprise/scripts/dottednames.js @@ -10,9 +10,9 @@ const fs = require('fs') const path = require('path') const { readRules } = require('./rules') -const sourceDirPath = path.resolve(__dirname, '../rules') +const sourceDirPath = path.resolve(__dirname, '../source/rules') // Note: we can't put the output file in the fs.watched directory -const outPath = path.resolve(__dirname, '../types/dottednames.json') +const outPath = path.resolve(__dirname, '../source/types/dottednames.json') function persistJsonFileFromYaml() { const rules = readRules() diff --git a/source/scripts/fetch-releases.js b/mon-entreprise/scripts/fetch-releases.js similarity index 100% rename from source/scripts/fetch-releases.js rename to mon-entreprise/scripts/fetch-releases.js diff --git a/source/scripts/fetch-stats.js b/mon-entreprise/scripts/fetch-stats.js similarity index 100% rename from source/scripts/fetch-stats.js rename to mon-entreprise/scripts/fetch-stats.js diff --git a/source/scripts/i18n/check-missing-UI-translation.js b/mon-entreprise/scripts/i18n/check-missing-UI-translation.js similarity index 100% rename from source/scripts/i18n/check-missing-UI-translation.js rename to mon-entreprise/scripts/i18n/check-missing-UI-translation.js diff --git a/source/scripts/i18n/check-missing-rule-translation.js b/mon-entreprise/scripts/i18n/check-missing-rule-translation.js similarity index 100% rename from source/scripts/i18n/check-missing-rule-translation.js rename to mon-entreprise/scripts/i18n/check-missing-rule-translation.js diff --git a/i18next-parser.config.js b/mon-entreprise/scripts/i18n/parser.config.js similarity index 95% rename from i18next-parser.config.js rename to mon-entreprise/scripts/i18n/parser.config.js index 8115205b2..43890e090 100644 --- a/i18next-parser.config.js +++ b/mon-entreprise/scripts/i18n/parser.config.js @@ -50,12 +50,12 @@ module.exports = { // Namespace separator used in your translation keys // If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance. - output: 'source/locales/static-analysis-$LOCALE.json', + output: '../../source/locales/static-analysis-$LOCALE.json', // Supports $LOCALE and $NAMESPACE injection // Supports JSON (.json) and YAML (.yml) file formats // Where to write the locale files relative to process.cwd() - input: './source/**/*.{jsx,tsx,js,ts}', + input: '../../source/**/*.{jsx,tsx,js,ts}', // An array of globs that describe where to look for source files // relative to the location of the configuration file diff --git a/source/scripts/i18n/translate-rules.js b/mon-entreprise/scripts/i18n/translate-rules.js similarity index 100% rename from source/scripts/i18n/translate-rules.js rename to mon-entreprise/scripts/i18n/translate-rules.js diff --git a/source/scripts/i18n/translate-ui.js b/mon-entreprise/scripts/i18n/translate-ui.js similarity index 100% rename from source/scripts/i18n/translate-ui.js rename to mon-entreprise/scripts/i18n/translate-ui.js diff --git a/source/scripts/i18n/utils.js b/mon-entreprise/scripts/i18n/utils.js similarity index 98% rename from source/scripts/i18n/utils.js rename to mon-entreprise/scripts/i18n/utils.js index 3408b603a..bc9f083a4 100644 --- a/source/scripts/i18n/utils.js +++ b/mon-entreprise/scripts/i18n/utils.js @@ -117,7 +117,7 @@ function getRulesMissingTranslations() { const getUiMissingTranslations = () => { const staticKeys = require(path.resolve( - 'source/locales/static-analysis-fr.json' + '../../source/locales/static-analysis-fr.json' )) const translatedKeys = parse(fs.readFileSync(UiTranslationPath, 'utf-8')) diff --git a/source/scripts/prepare.js b/mon-entreprise/scripts/prepare.js similarity index 100% rename from source/scripts/prepare.js rename to mon-entreprise/scripts/prepare.js diff --git a/source/scripts/rules.js b/mon-entreprise/scripts/rules.js similarity index 91% rename from source/scripts/rules.js rename to mon-entreprise/scripts/rules.js index 9101941c3..e61deca19 100644 --- a/source/scripts/rules.js +++ b/mon-entreprise/scripts/rules.js @@ -5,7 +5,7 @@ const fs = require('fs') const path = require('path') const yaml = require('yaml') -const publicodesDir = path.resolve(__dirname, '../rules') +const publicodesDir = path.resolve(__dirname, '../source/rules') function concatenateFilesInDir(dirPath = publicodesDir) { return fs diff --git a/source/scripts/utils.js b/mon-entreprise/scripts/utils.js similarity index 82% rename from source/scripts/utils.js rename to mon-entreprise/scripts/utils.js index ab64a1666..c65ac58ec 100644 --- a/source/scripts/utils.js +++ b/mon-entreprise/scripts/utils.js @@ -1,6 +1,6 @@ const path = require('path') const fs = require('fs') -const dataDir = path.resolve(__dirname, '../data/') +const dataDir = path.resolve(__dirname, '../source/data/') exports.createDataDir = () => { if (!fs.existsSync(dataDir)) { diff --git a/serve.infrance.json b/mon-entreprise/serve.infrance.json similarity index 100% rename from serve.infrance.json rename to mon-entreprise/serve.infrance.json diff --git a/serve.mon-entreprise.json b/mon-entreprise/serve.mon-entreprise.json similarity index 100% rename from serve.mon-entreprise.json rename to mon-entreprise/serve.mon-entreprise.json diff --git a/serve.publicodes.json b/mon-entreprise/serve.publicodes.json similarity index 100% rename from serve.publicodes.json rename to mon-entreprise/serve.publicodes.json diff --git a/source/Provider.tsx b/mon-entreprise/source/Provider.tsx similarity index 92% rename from source/Provider.tsx rename to mon-entreprise/source/Provider.tsx index 8deb5e180..b947da513 100644 --- a/source/Provider.tsx +++ b/mon-entreprise/source/Provider.tsx @@ -2,16 +2,15 @@ import { ThemeColorsProvider } from 'Components/utils/colors' import { SitePathProvider, SitePaths } from 'Components/utils/SitePathsContext' import { TrackerProvider } from 'Components/utils/withTracker' import { createBrowserHistory } from 'history' -import { AvailableLangs } from 'i18n' import i18next from 'i18next' import React, { createContext, useEffect, useMemo } from 'react' -import { I18nextProvider, useTranslation } from 'react-i18next' +import { I18nextProvider } from 'react-i18next' import { Provider as ReduxProvider } from 'react-redux' import { Router } from 'react-router-dom' import reducers, { RootState } from 'Reducers/rootReducer' import { applyMiddleware, compose, createStore, Middleware, Store } from 'redux' import thunk from 'redux-thunk' -import Tracker from 'Tracker' +import Tracker from './Tracker' import { inIframe } from './utils' declare global { @@ -56,13 +55,13 @@ export type ProviderProps = { } export default function Provider({ - tracker, + tracker = new Tracker(), basename, - sitePaths, reduxMiddlewares, initialStore, onStoreCreated, - children + children, + sitePaths = {} as SitePaths }: ProviderProps) { const history = useMemo( () => @@ -118,9 +117,9 @@ export default function Provider({ - + - + <>{children} diff --git a/source/Tracker.ts b/mon-entreprise/source/Tracker.ts similarity index 100% rename from source/Tracker.ts rename to mon-entreprise/source/Tracker.ts diff --git a/source/actions/actions.ts b/mon-entreprise/source/actions/actions.ts similarity index 98% rename from source/actions/actions.ts rename to mon-entreprise/source/actions/actions.ts index d02c01049..f138dbcc2 100644 --- a/source/actions/actions.ts +++ b/mon-entreprise/source/actions/actions.ts @@ -2,7 +2,7 @@ import { SitePaths } from 'Components/utils/SitePathsContext' import { History } from 'history' import { RootState, SimulationConfig } from 'Reducers/rootReducer' import { ThunkAction } from 'redux-thunk' -import { DottedName, Situation } from 'Rules' +import { DottedName } from 'Rules' import { deletePersistedSimulation } from '../storage/persistSimulation' import { CompanyStatusAction } from './companyStatusActions' diff --git a/source/actions/companyCreationChecklistActions.ts b/mon-entreprise/source/actions/companyCreationChecklistActions.ts similarity index 100% rename from source/actions/companyCreationChecklistActions.ts rename to mon-entreprise/source/actions/companyCreationChecklistActions.ts diff --git a/source/actions/companyStatusActions.ts b/mon-entreprise/source/actions/companyStatusActions.ts similarity index 100% rename from source/actions/companyStatusActions.ts rename to mon-entreprise/source/actions/companyStatusActions.ts diff --git a/source/actions/existingCompanyActions.js b/mon-entreprise/source/actions/existingCompanyActions.js similarity index 100% rename from source/actions/existingCompanyActions.js rename to mon-entreprise/source/actions/existingCompanyActions.js diff --git a/source/actions/hiringChecklistAction.ts b/mon-entreprise/source/actions/hiringChecklistAction.ts similarity index 100% rename from source/actions/hiringChecklistAction.ts rename to mon-entreprise/source/actions/hiringChecklistAction.ts diff --git a/source/api/sirene.ts b/mon-entreprise/source/api/sirene.ts similarity index 100% rename from source/api/sirene.ts rename to mon-entreprise/source/api/sirene.ts diff --git a/source/components/Banner.css b/mon-entreprise/source/components/Banner.css similarity index 100% rename from source/components/Banner.css rename to mon-entreprise/source/components/Banner.css diff --git a/source/components/Banner.tsx b/mon-entreprise/source/components/Banner.tsx similarity index 93% rename from source/components/Banner.tsx rename to mon-entreprise/source/components/Banner.tsx index 881e549ad..74ea425f4 100644 --- a/source/components/Banner.tsx +++ b/mon-entreprise/source/components/Banner.tsx @@ -2,7 +2,7 @@ import React from 'react' import emoji from 'react-easy-emoji' import { useSelector } from 'react-redux' import { firstStepCompletedSelector } from 'Selectors/simulationSelectors' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' import './Banner.css' type BannerProps = { diff --git a/source/components/BarChart.tsx b/mon-entreprise/source/components/BarChart.tsx similarity index 98% rename from source/components/BarChart.tsx rename to mon-entreprise/source/components/BarChart.tsx index 0b0a095bc..3c521cbfa 100644 --- a/source/components/BarChart.tsx +++ b/mon-entreprise/source/components/BarChart.tsx @@ -3,7 +3,7 @@ import emoji from 'react-easy-emoji' import { animated, config, useSpring } from 'react-spring' import useDisplayOnIntersecting from 'Components/utils/useDisplayOnIntersecting' import { ThemeColorsContext } from 'Components/utils/colors' -import { formatValue } from 'Engine/format' +import { formatValue } from 'publicodes' import { useTranslation } from 'react-i18next' const ANIMATION_SPRING = config.gentle diff --git a/source/components/CompanyDetails.tsx b/mon-entreprise/source/components/CompanyDetails.tsx similarity index 100% rename from source/components/CompanyDetails.tsx rename to mon-entreprise/source/components/CompanyDetails.tsx diff --git a/source/components/Controls.css b/mon-entreprise/source/components/Controls.css similarity index 100% rename from source/components/Controls.css rename to mon-entreprise/source/components/Controls.css diff --git a/source/components/Controls.tsx b/mon-entreprise/source/components/Controls.tsx similarity index 90% rename from source/components/Controls.tsx rename to mon-entreprise/source/components/Controls.tsx index 7e454989e..9f58f5848 100644 --- a/source/components/Controls.tsx +++ b/mon-entreprise/source/components/Controls.tsx @@ -1,16 +1,15 @@ import { goToQuestion, hideControl } from 'Actions/actions' +import animate from 'Components/ui/animate' import { useControls, useInversionFail } from 'Components/utils/EngineContext' -import { makeJsx } from 'Engine/evaluation' import React from 'react' import emoji from 'react-easy-emoji' import { useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { RootState } from 'Reducers/rootReducer' -import animate from 'Ui/animate' +import { answeredQuestionsSelector } from 'Selectors/simulationSelectors' import './Controls.css' import { Markdown } from './utils/markdown' import { ScrollToElement } from './utils/Scroll' -import { answeredQuestionsSelector } from 'Selectors/simulationSelectors' export default function Controls() { const { t } = useTranslation() @@ -48,12 +47,7 @@ export default function Controls() {
{emoji(level == 'avertissement' ? '⚠️' : 'ℹ️')}
- {message ? ( - - ) : ( - {makeJsx(evaluated)} - )} - + {solution && !answeredQuestions?.includes(solution.cible) && (
*/} + + ) +} +function BackToSimulation() { + const dispatch = useDispatch() + const handleClick = useCallback(() => { + dispatch(goBackToSimulation()) + }, []) + return ( + + ) +} diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx similarity index 96% rename from source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx index 83132bad9..265045d39 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/Result.tsx @@ -1,12 +1,12 @@ import RuleLink from 'Components/RuleLink' import { useEvaluation } from 'Components/utils/EngineContext' -import { formatValue } from 'Engine/format' +import { formatValue } from 'publicodes' import React from 'react' import emoji from 'react-easy-emoji' import { Trans } from 'react-i18next' import Skeleton from 'react-loading-skeleton' import ReactToPrint from 'react-to-print' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' import simulationConfig from './config.yaml' import { DottedName } from 'Rules' diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/config.yaml b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/config.yaml similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/config.yaml rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/config.yaml diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx index d4b7098da..e2bc5f84d 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideDéclarationIndépendant/index.tsx @@ -6,8 +6,8 @@ import Warning from 'Components/ui/WarningBlock' import { useEvaluation, EngineContext } from 'Components/utils/EngineContext' import { ScrollToTop } from 'Components/utils/Scroll' import useDisplayOnIntersecting from 'Components/utils/useDisplayOnIntersecting' -import RuleInput from 'Engine/RuleInput' -import { ParsedRule } from 'Engine/types' +import RuleInput from 'Components/conversation/RuleInput' +import { ParsedRule } from 'publicodes' import React, { useCallback, useEffect, @@ -21,7 +21,7 @@ import { RootState } from 'Reducers/rootReducer' import { DottedName } from 'Rules' import { situationSelector } from 'Selectors/simulationSelectors' import styled from 'styled-components' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' import { CompanySection } from '../Home' import simulationConfig from './config.yaml' import { Results } from './Result' diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx similarity index 97% rename from source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx index 971ebf59b..b6e1910cb 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/AideOrganismeLocal.tsx @@ -2,7 +2,7 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { RootState } from 'Reducers/rootReducer' -import animate from 'Ui/animate' +import animate from 'Components/ui/animate' import aideOrganismeSvg from './aideOrganisme.svg' const aideMidiPyrenéesAutoEntrepreneur = (state: RootState) => { diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx index 20de524d1..3612df6d5 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Embaucher.tsx @@ -7,8 +7,8 @@ import { Helmet } from 'react-helmet' import { Trans, useTranslation } from 'react-i18next' import { connect, useSelector } from 'react-redux' import { RootState } from 'Reducers/rootReducer' -import Animate from 'Ui/animate' -import { CheckItem, Checklist, ChecklistProps } from 'Ui/Checklist' +import Animate from 'Components/ui/animate' +import { CheckItem, Checklist, ChecklistProps } from 'Components/ui/Checklist' type EmbaucherProps = { onChecklistInitialization: ChecklistProps['onInitialization'] diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx similarity index 99% rename from source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx index 3d2f9717f..eccd41a0d 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Home.tsx @@ -16,7 +16,7 @@ import { useDispatch, useSelector } from 'react-redux' import { Link } from 'react-router-dom' import { Company } from 'Reducers/inFranceAppReducer' import { RootState } from 'Reducers/rootReducer' -import * as Animate from 'Ui/animate' +import * as Animate from 'Components/ui/animate' import { productionMode } from '../../../../utils' import AideOrganismeLocal from './AideOrganismeLocal' import businessPlan from './businessPlan.svg' diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx similarity index 97% rename from source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx index 10a9883a9..c09ede567 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SchemeSelection.tsx @@ -4,7 +4,7 @@ import emoji from 'react-easy-emoji' import { Helmet } from 'react-helmet' import { Trans, useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' -import animate from 'Ui/animate' +import animate from 'Components/ui/animate' export default function SchemeChoice() { const sitePaths = useContext(SitePathsContext) diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx similarity index 95% rename from source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx index 7bba9efc8..5cce71bf9 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/SécuritéSociale.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Helmet } from 'react-helmet' import { Trans, useTranslation } from 'react-i18next' -import * as Animate from 'Ui/animate' +import * as Animate from 'Components/ui/animate' import Video from './Video' export default function SocialSecurity() { diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/Video.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Video.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Gérer/Video.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/Video.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/aideOrganisme.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/aideOrganisme.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Gérer/aideOrganisme.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/aideOrganisme.svg diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/businessPlan.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/businessPlan.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Gérer/businessPlan.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/businessPlan.svg diff --git a/source/sites/mon-entreprise.fr/pages/Gérer/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/index.tsx similarity index 96% rename from source/sites/mon-entreprise.fr/pages/Gérer/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/index.tsx index 0503fafa0..7cbae4e83 100644 --- a/source/sites/mon-entreprise.fr/pages/Gérer/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Gérer/index.tsx @@ -2,7 +2,7 @@ import { ScrollToTop } from 'Components/utils/Scroll' import { SitePathsContext } from 'Components/utils/SitePathsContext' import React, { useContext } from 'react' import { Trans } from 'react-i18next' -import { Route, Switch } from 'react-router' +import { Route, Switch } from 'react-router-dom' import { NavLink, useLocation } from 'react-router-dom' import AideDéclarationIndépendant from './AideDéclarationIndépendant/index' import Embaucher from './Embaucher' diff --git a/source/sites/mon-entreprise.fr/pages/Iframes/IframeFooter.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/IframeFooter.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Iframes/IframeFooter.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/IframeFooter.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Iframes/SimulateurEmbauche.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/SimulateurEmbauche.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Iframes/SimulateurEmbauche.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/SimulateurEmbauche.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Iframes/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/index.tsx similarity index 97% rename from source/sites/mon-entreprise.fr/pages/Iframes/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/index.tsx index 05730dffd..fe7046910 100644 --- a/source/sites/mon-entreprise.fr/pages/Iframes/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Iframes/index.tsx @@ -1,6 +1,6 @@ import { IsEmbeddedContext } from 'Components/utils/embeddedContext' import React from 'react' -import { Route } from 'react-router' +import { Route } from 'react-router-dom' import { inIframe } from '../../../../utils' import SimulateurChômagePartiel from '../Coronavirus' import SimulateurArtisteAuteur from '../Simulateurs/ArtisteAuteur' diff --git a/source/sites/mon-entreprise.fr/pages/Landing/Landing.css b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/Landing.css similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Landing/Landing.css rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/Landing.css diff --git a/source/sites/mon-entreprise.fr/pages/Landing/Landing.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/Landing.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Landing/Landing.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/Landing.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Landing/illustration.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/illustration.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Landing/illustration.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Landing/illustration.svg diff --git a/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx similarity index 99% rename from source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx index 7a3f99343..126dfb28e 100644 --- a/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx @@ -4,7 +4,7 @@ import { ScrollToTop } from 'Components/utils/Scroll' import { SitePathsContext } from 'Components/utils/SitePathsContext' import React, { useContext, useEffect } from 'react' import emoji from 'react-easy-emoji' -import { Redirect, useHistory, useRouteMatch } from 'react-router' +import { Redirect, useHistory, useRouteMatch } from 'react-router-dom' import { Link, NavLink } from 'react-router-dom' import styled from 'styled-components' import useSWR from 'swr' diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx index b26525ae1..bf79accda 100644 --- a/source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/ArtisteAuteur.tsx @@ -7,14 +7,14 @@ import 'Components/TargetSelection.css' import { IsEmbeddedContext } from 'Components/utils/embeddedContext' import { EngineContext, useEvaluation } from 'Components/utils/EngineContext' import Value from 'Components/EngineValue' -import RuleInput from 'Engine/RuleInput' +import RuleInput from 'Components/conversation/RuleInput' import React, { createContext, useContext, useEffect, useState } from 'react' import { Trans } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { DottedName } from 'Rules' import { situationSelector } from 'Selectors/simulationSelectors' import styled from 'styled-components' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' const InitialRenderContext = createContext(false) function useInitialRender() { diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/AssimiléSalarié.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/AssimiléSalarié.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/AssimiléSalarié.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/AssimiléSalarié.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/AutoEntrepreneur.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/AutoEntrepreneur.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/AutoEntrepreneur.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/AutoEntrepreneur.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/Home.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Home.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/Home.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Home.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/Indépendant.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Indépendant.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/Indépendant.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Indépendant.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx similarity index 87% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx index e83b571d5..a8f978163 100644 --- a/source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/Salarié.tsx @@ -1,5 +1,6 @@ import Banner from 'Components/Banner' import PreviousSimulationBanner from 'Components/PreviousSimulationBanner' +import RuleLink from 'Components/RuleLink' import SalaryExplanation from 'Components/SalaryExplanation' import Simulation from 'Components/Simulation' import salariéConfig from 'Components/simulationConfigs/salarié.yaml' @@ -79,21 +80,14 @@ function SeoExplanations() { />

Par ailleurs depuis 2019, l' - - impôt sur le revenu - {' '} - est prélevé à la source. Pour ce faire, la direction générale des - finances publiques (DGFiP) transmet à l'employeur le taux d'imposition - calculé à partir de la déclaration de revenu du salarié. Si ce taux est - inconnu, par exemple lors d'une première année d'activité, l'employeur - utilise le{' '} - + impôt sur le revenu est prélevé + à la source. Pour ce faire, la direction générale des finances publiques + (DGFiP) transmet à l'employeur le taux d'imposition calculé à partir de + la déclaration de revenu du salarié. Si ce taux est inconnu, par exemple + lors d'une première année d'activité, l'employeur utilise le{' '} + taux neutre - + .

@@ -115,11 +109,9 @@ function SeoExplanations() {

Il existe des{' '} - + aides différées - {' '} + {' '} à l'embauche qui ne sont pas toutes prises en compte par notre simulateur, vous pouvez les retrouver sur{' '} diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/SchemeComparaison.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/SchemeComparaison.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/SchemeComparaison.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/SchemeComparaison.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx index 4ab3f5955..dce2bc66d 100644 --- a/source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Simulateurs/index.tsx @@ -5,7 +5,7 @@ import { SitePathsContext } from 'Components/utils/SitePathsContext' import React, { useContext, useEffect } from 'react' import { Trans } from 'react-i18next' import { useSelector } from 'react-redux' -import { Route, Switch } from 'react-router' +import { Route, Switch } from 'react-router-dom' import { Link, useLocation } from 'react-router-dom' import ArtisteAuteur from './ArtisteAuteur' import AssimiléSalarié from './AssimiléSalarié' diff --git a/source/sites/mon-entreprise.fr/pages/Stats/LazyStats.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Stats/LazyStats.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/Stats/LazyStats.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Stats/LazyStats.tsx diff --git a/source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx similarity index 99% rename from source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx index 75c220593..7ffe587d4 100644 --- a/source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/Stats/Stats.tsx @@ -3,6 +3,7 @@ import MoreInfosOnUs from 'Components/MoreInfosOnUs' import { StackedBarChart } from 'Components/StackedBarChart' import { ThemeColorsContext } from 'Components/utils/colors' import { ScrollToTop } from 'Components/utils/Scroll' +import { formatValue } from 'publicodes' import { groupWith } from 'ramda' import React, { useContext, useState } from 'react' import emoji from 'react-easy-emoji' @@ -20,10 +21,6 @@ import { } from 'recharts' import DefaultTooltipContent from 'recharts/lib/component/DefaultTooltipContent' import styled from 'styled-components' -import { - formatPercentage, - formatValue -} from '../../../../../source/engine/format' import statsJson from '../../../../data/stats.json' import { capitalise0 } from '../../../../utils' import Privacy from '../../layout/Footer/Privacy' diff --git a/source/sites/mon-entreprise.fr/pages/integration/Iframe.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Iframe.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/Iframe.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Iframe.tsx diff --git a/source/sites/mon-entreprise.fr/pages/integration/Library.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Library.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/Library.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Library.tsx diff --git a/source/sites/mon-entreprise.fr/pages/integration/Options.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Options.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/integration/Options.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Options.tsx index a9f55561e..686aca2ef 100644 --- a/source/sites/mon-entreprise.fr/pages/integration/Options.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/Options.tsx @@ -3,7 +3,7 @@ import React, { useContext } from 'react' import emoji from 'react-easy-emoji' import { Trans } from 'react-i18next' import { Link } from 'react-router-dom' -import { icons } from 'Ui/SocialIcon' +import { icons } from 'Components/ui/SocialIcon' import illustration from './illustration.png' export default function Options() { diff --git a/source/sites/mon-entreprise.fr/pages/integration/iframe.css b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/iframe.css similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/iframe.css rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/iframe.css diff --git a/source/sites/mon-entreprise.fr/pages/integration/illustration.png b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/illustration.png similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/illustration.png rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/illustration.png diff --git a/source/sites/mon-entreprise.fr/pages/integration/images/apec.png b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/apec.png similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/images/apec.png rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/apec.png diff --git a/source/sites/mon-entreprise.fr/pages/integration/images/cci.png b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/cci.png similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/images/cci.png rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/cci.png diff --git a/source/sites/mon-entreprise.fr/pages/integration/images/logo-betagouv.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/logo-betagouv.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/images/logo-betagouv.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/logo-betagouv.svg diff --git a/source/sites/mon-entreprise.fr/pages/integration/images/min-tra.jpg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/min-tra.jpg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/images/min-tra.jpg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/min-tra.jpg diff --git a/source/images/références/pole-emploi.png b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/pole-emploi.png similarity index 100% rename from source/images/références/pole-emploi.png rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/images/pole-emploi.png diff --git a/source/sites/mon-entreprise.fr/pages/integration/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/index.tsx similarity index 94% rename from source/sites/mon-entreprise.fr/pages/integration/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/index.tsx index 19030abca..b15106b53 100644 --- a/source/sites/mon-entreprise.fr/pages/integration/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/integration/index.tsx @@ -2,7 +2,7 @@ import { ScrollToTop } from 'Components/utils/Scroll' import { SitePathsContext } from 'Components/utils/SitePathsContext' import React, { useContext } from 'react' import { Trans } from 'react-i18next' -import { Route, Switch, useLocation } from 'react-router' +import { Route, Switch, useLocation } from 'react-router-dom' import { Link } from 'react-router-dom' import Iframe from './Iframe' import Library from './Library' diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx similarity index 98% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx index c02c9c6e9..c34744c16 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/Activité.tsx @@ -6,7 +6,7 @@ import React, { useContext } from 'react' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import { Redirect } from 'react-router-dom' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' import { selectSeuilRevenus } from './actions' import { getTranslatedActivité } from './activitésData' import { ActivitéSelection } from './ActivitésSelection' @@ -14,7 +14,7 @@ import ExceptionsExonération from './ExceptionsExonération' import NextButton from './NextButton' import { estExonéréeSelector } from './selectors' import { StoreContext } from './StoreContext' -import { formatValue } from 'Engine/format' +import { formatValue } from 'publicodes' export default function Activité({ match: { diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx similarity index 97% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx index 619187011..33f353973 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ActivitésSelection.tsx @@ -7,9 +7,9 @@ import emoji from 'react-easy-emoji' import { Helmet } from 'react-helmet' import { Trans, useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' -import Animate from 'Ui/animate' -import Checkbox from 'Ui/Checkbox' -import InfoBulle from 'Ui/InfoBulle' +import Animate from 'Components/ui/animate' +import Checkbox from 'Components/ui/Checkbox' +import InfoBulle from 'Components/ui/InfoBulle' import { debounce } from '../../../../utils' import { toggleActivité } from './actions' import { activités, getTranslatedActivité } from './activitésData' diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx similarity index 95% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx index 780bb932c..c0e9935eb 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/ExceptionsExonération.tsx @@ -1,6 +1,6 @@ import React, { useContext } from 'react' import { Trans } from 'react-i18next' -import { CheckItem, Checklist } from 'Ui/Checklist' +import { CheckItem, Checklist } from 'Components/ui/Checklist' import { changeCritèreExonération } from './actions' import { StoreContext } from './StoreContext' diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/NextButton.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/NextButton.tsx similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/NextButton.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/NextButton.tsx diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/StoreContext.js b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/StoreContext.js similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/StoreContext.js rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/StoreContext.js diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx similarity index 99% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx index 8b97f6101..ddb80ebb2 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/VotreSituation.tsx @@ -4,7 +4,7 @@ import React, { useContext } from 'react' import { Helmet } from 'react-helmet' import { Trans, useTranslation } from 'react-i18next' import { Link, Redirect } from 'react-router-dom' -import Animate from 'Ui/animate' +import Animate from 'Components/ui/animate' import { ActivitéCard } from './ActivitésSelection' import illustration from './images/multitasking.svg' import { diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/actions.ts b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/actions.ts similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/actions.ts rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/actions.ts diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.en.yaml b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.en.yaml similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.en.yaml rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.en.yaml diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.yaml b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.yaml similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.yaml rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activités.yaml diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activitésData.ts b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activitésData.ts similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activitésData.ts rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/activitésData.ts diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/car.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/car.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/car.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/car.svg diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/checklist.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/checklist.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/checklist.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/checklist.svg diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/multitasking.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/multitasking.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/multitasking.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/multitasking.svg diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/pizzaSharing.svg b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/pizzaSharing.svg similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/pizzaSharing.svg rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/images/pizzaSharing.svg diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx similarity index 96% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx index d06e3398b..cef9465e9 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/index.tsx @@ -1,7 +1,7 @@ import { SitePathsContext } from 'Components/utils/SitePathsContext' import React, { useContext } from 'react' import { Trans } from 'react-i18next' -import { Route, Switch } from 'react-router' +import { Route, Switch } from 'react-router-dom' import { NavLink } from 'react-router-dom' import Activité from './Activité' import ActivitésSelection from './ActivitésSelection' diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts similarity index 91% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts index 08cef3b68..0706d16df 100644 --- a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts +++ b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/reducer.ts @@ -10,11 +10,11 @@ import { const activitéReducer = reducerActivité => combineReducers({ - effectuée: (state: boolean = false, { type, activité }: Action): boolean => + effectuée: (state = false, { type, activité }: Action): boolean => type === 'TOGGLE_ACTIVITÉ_EFFECTUÉE' && reducerActivité === activité ? !state - : state, - vue: (state: boolean = false, { type, activité }: Action): boolean => { + : !!state, + vue: (state = false, { type, activité }: Action): boolean => { if (type === 'ACTIVITÉ_VUE' && reducerActivité === activité) { return true } @@ -24,7 +24,7 @@ const activitéReducer = reducerActivité => ) { return false } - return state + return !!state }, seuilRevenus: ( state = getMinimumDéclaration(reducerActivité), diff --git a/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/selectors.js b/mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/selectors.js similarity index 100% rename from source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/selectors.js rename to mon-entreprise/source/sites/mon-entreprise.fr/pages/ÉconomieCollaborative/selectors.js diff --git a/source/sites/mon-entreprise.fr/redirects.js b/mon-entreprise/source/sites/mon-entreprise.fr/redirects.js similarity index 87% rename from source/sites/mon-entreprise.fr/redirects.js rename to mon-entreprise/source/sites/mon-entreprise.fr/redirects.js index 587c45fb8..3f9a12a07 100644 --- a/source/sites/mon-entreprise.fr/redirects.js +++ b/mon-entreprise/source/sites/mon-entreprise.fr/redirects.js @@ -1,6 +1,6 @@ import React from 'react' import { Redirect } from 'react-router-dom' -import netlifyToml from '../../../netlify.toml' +import netlifyToml from '../../../../netlify.toml' export default netlifyToml.redirects .filter(({ from, status }) => status === 301 && !from.startsWith('https')) diff --git a/source/sites/mon-entreprise.fr/robots.txt b/mon-entreprise/source/sites/mon-entreprise.fr/robots.txt similarity index 100% rename from source/sites/mon-entreprise.fr/robots.txt rename to mon-entreprise/source/sites/mon-entreprise.fr/robots.txt diff --git a/source/sites/mon-entreprise.fr/sitePaths.ts b/mon-entreprise/source/sites/mon-entreprise.fr/sitePaths.ts similarity index 96% rename from source/sites/mon-entreprise.fr/sitePaths.ts rename to mon-entreprise/source/sites/mon-entreprise.fr/sitePaths.ts index 1394ce744..229c7e954 100644 --- a/source/sites/mon-entreprise.fr/sitePaths.ts +++ b/mon-entreprise/source/sites/mon-entreprise.fr/sitePaths.ts @@ -1,6 +1,4 @@ -import { encodeRuleName } from 'Engine/ruleUtils' import { map, reduce, toPairs, zipObj } from 'ramda' -import { DottedName } from 'Rules' import { LegalStatus } from 'Selectors/companyStatusSelectors' export const LANDING_LEGAL_STATUS_LIST: Array = [ @@ -38,9 +36,7 @@ const sitePathsFr = { soleProprietorship: '/responsabilité', directorStatus: '/dirigeant', autoEntrepreneur: '/auto-entrepreneur-ou-entreprise-individuelle', - multipleAssociates: '/nombre-associés', - minorityDirector: '/gérant-majoritaire-ou-minoritaire' } }, @@ -73,8 +69,7 @@ const sitePathsFr = { library: '/bibliothèque-de-calcul' }, documentation: { - index: '/documentation', - rule: (dottedName: DottedName) => '/' + encodeRuleName(dottedName) + index: '/documentation' } } as const diff --git a/source/sites/mon-entreprise.fr/sitemap.en.txt b/mon-entreprise/source/sites/mon-entreprise.fr/sitemap.en.txt similarity index 100% rename from source/sites/mon-entreprise.fr/sitemap.en.txt rename to mon-entreprise/source/sites/mon-entreprise.fr/sitemap.en.txt diff --git a/source/sites/mon-entreprise.fr/sitemap.fr.txt b/mon-entreprise/source/sites/mon-entreprise.fr/sitemap.fr.txt similarity index 100% rename from source/sites/mon-entreprise.fr/sitemap.fr.txt rename to mon-entreprise/source/sites/mon-entreprise.fr/sitemap.fr.txt diff --git a/source/sites/publi.codes/App.tsx b/mon-entreprise/source/sites/publi.codes/App.tsx similarity index 93% rename from source/sites/publi.codes/App.tsx rename to mon-entreprise/source/sites/publi.codes/App.tsx index 19a5f4f29..0375900a8 100644 --- a/source/sites/publi.codes/App.tsx +++ b/mon-entreprise/source/sites/publi.codes/App.tsx @@ -1,9 +1,9 @@ // TODO : load translation only if en -import { hot } from 'react-hot-loader' +import 'Components/ui/index.css' import 'iframe-resizer' -import React, { useEffect } from 'react' +import React from 'react' +import { hot } from 'react-hot-loader' import { Route, Switch } from 'react-router-dom' -import 'Ui/index.css' import Provider from '../../Provider' import redirects from '../mon-entreprise.fr/redirects' import Landing from './Landing' diff --git a/source/sites/publi.codes/Header.tsx b/mon-entreprise/source/sites/publi.codes/Header.tsx similarity index 100% rename from source/sites/publi.codes/Header.tsx rename to mon-entreprise/source/sites/publi.codes/Header.tsx diff --git a/source/sites/publi.codes/Landing.tsx b/mon-entreprise/source/sites/publi.codes/Landing.tsx similarity index 91% rename from source/sites/publi.codes/Landing.tsx rename to mon-entreprise/source/sites/publi.codes/Landing.tsx index a23585e93..777f3c6fc 100644 --- a/source/sites/publi.codes/Landing.tsx +++ b/mon-entreprise/source/sites/publi.codes/Landing.tsx @@ -1,6 +1,6 @@ import { MarkdownWithAnchorLinks } from 'Components/utils/markdown' import { ScrollToTop } from 'Components/utils/Scroll' -import publicodeReadme from 'Engine/README.md' +import publicodeReadme from '../../../../publicodes/README.md' import React, { useEffect } from 'react' import { Header } from './Header' import { NavLink } from 'react-router-dom' diff --git a/source/sites/publi.codes/LazyStudio.tsx b/mon-entreprise/source/sites/publi.codes/LazyStudio.tsx similarity index 100% rename from source/sites/publi.codes/LazyStudio.tsx rename to mon-entreprise/source/sites/publi.codes/LazyStudio.tsx diff --git a/source/sites/publi.codes/Mécanismes.tsx b/mon-entreprise/source/sites/publi.codes/Mécanismes.tsx similarity index 93% rename from source/sites/publi.codes/Mécanismes.tsx rename to mon-entreprise/source/sites/publi.codes/Mécanismes.tsx index c9fa14e63..df2206932 100644 --- a/source/sites/publi.codes/Mécanismes.tsx +++ b/mon-entreprise/source/sites/publi.codes/Mécanismes.tsx @@ -1,8 +1,8 @@ import { Markdown } from 'Components/utils/markdown' import { ScrollToTop } from 'Components/utils/Scroll' -import mecanisms from 'Engine/mecanisms.yaml' +import mecanisms from '../../../../publicodes/source/mecanisms.yaml' import React, { useEffect } from 'react' -import { useLocation } from 'react-router' +import { useLocation } from 'react-router-dom' import { HashLink as Link } from 'react-router-hash-link' import { capitalise0 } from '../../utils' import { Header } from './Header' diff --git a/source/sites/publi.codes/Studio.tsx b/mon-entreprise/source/sites/publi.codes/Studio.tsx similarity index 98% rename from source/sites/publi.codes/Studio.tsx rename to mon-entreprise/source/sites/publi.codes/Studio.tsx index 525b5629a..2df6eb256 100644 --- a/source/sites/publi.codes/Studio.tsx +++ b/mon-entreprise/source/sites/publi.codes/Studio.tsx @@ -1,12 +1,12 @@ // import { ControlledEditor } from '@monaco-editor/react' -import Engine from 'Engine' -import { formatValue } from 'Engine/format' +import Engine from 'publicodes' +import { formatValue } from 'publicodes' import yaml from 'yaml' import { last } from 'ramda' import React, { useCallback, useEffect, useMemo, useState } from 'react' import emoji from 'react-easy-emoji' import MonacoEditor from 'react-monaco-editor' -import { useLocation } from 'react-router' +import { useLocation } from 'react-router-dom' import styled from 'styled-components' const EXAMPLE_CODE = ` diff --git a/source/sites/publi.codes/entry.tsx b/mon-entreprise/source/sites/publi.codes/entry.tsx similarity index 100% rename from source/sites/publi.codes/entry.tsx rename to mon-entreprise/source/sites/publi.codes/entry.tsx diff --git a/source/storage/persistEverything.ts b/mon-entreprise/source/storage/persistEverything.ts similarity index 100% rename from source/storage/persistEverything.ts rename to mon-entreprise/source/storage/persistEverything.ts diff --git a/source/storage/persistSimulation.ts b/mon-entreprise/source/storage/persistSimulation.ts similarity index 100% rename from source/storage/persistSimulation.ts rename to mon-entreprise/source/storage/persistSimulation.ts diff --git a/source/storage/safeLocalStorage.ts b/mon-entreprise/source/storage/safeLocalStorage.ts similarity index 100% rename from source/storage/safeLocalStorage.ts rename to mon-entreprise/source/storage/safeLocalStorage.ts diff --git a/source/storage/serializeSimulation.ts b/mon-entreprise/source/storage/serializeSimulation.ts similarity index 100% rename from source/storage/serializeSimulation.ts rename to mon-entreprise/source/storage/serializeSimulation.ts diff --git a/mon-entreprise/source/types/.gitignore b/mon-entreprise/source/types/.gitignore new file mode 100644 index 000000000..d2785045c --- /dev/null +++ b/mon-entreprise/source/types/.gitignore @@ -0,0 +1 @@ +dottednames.json diff --git a/source/types/app-env.d.ts b/mon-entreprise/source/types/app-env.d.ts similarity index 100% rename from source/types/app-env.d.ts rename to mon-entreprise/source/types/app-env.d.ts diff --git a/source/types/companyTypes.ts b/mon-entreprise/source/types/companyTypes.ts similarity index 100% rename from source/types/companyTypes.ts rename to mon-entreprise/source/types/companyTypes.ts diff --git a/source/types/css-prop.d.ts b/mon-entreprise/source/types/css-prop.d.ts similarity index 100% rename from source/types/css-prop.d.ts rename to mon-entreprise/source/types/css-prop.d.ts diff --git a/source/types/import-images.d.ts b/mon-entreprise/source/types/import-images.d.ts similarity index 100% rename from source/types/import-images.d.ts rename to mon-entreprise/source/types/import-images.d.ts diff --git a/source/types/import-markdown.d.ts b/mon-entreprise/source/types/import-markdown.d.ts similarity index 100% rename from source/types/import-markdown.d.ts rename to mon-entreprise/source/types/import-markdown.d.ts diff --git a/source/types/import-nearley.ts b/mon-entreprise/source/types/import-nearley.d.ts similarity index 100% rename from source/types/import-nearley.ts rename to mon-entreprise/source/types/import-nearley.d.ts diff --git a/source/types/import-yaml.ts b/mon-entreprise/source/types/import-yaml.ts similarity index 100% rename from source/types/import-yaml.ts rename to mon-entreprise/source/types/import-yaml.ts diff --git a/source/types/worker-loader.d.ts b/mon-entreprise/source/types/worker-loader.d.ts similarity index 100% rename from source/types/worker-loader.d.ts rename to mon-entreprise/source/types/worker-loader.d.ts diff --git a/source/utils.ts b/mon-entreprise/source/utils.ts similarity index 86% rename from source/utils.ts rename to mon-entreprise/source/utils.ts index e76fc83f9..fc83eba07 100644 --- a/source/utils.ts +++ b/mon-entreprise/source/utils.ts @@ -1,3 +1,5 @@ +import { formatValue } from 'publicodes' + export function capitalise0(name: undefined): undefined export function capitalise0(name: string): string export function capitalise0(name?: string) { @@ -67,3 +69,13 @@ export function getSessionStorage() { return undefined } } + +export const currencyFormat = (language: string) => ({ + isCurrencyPrefixed: !!formatValue({ + language, + nodeValue: 12, + unit: '€' + }).match(/^€/), + thousandSeparator: formatValue({ language, nodeValue: 1000 }).charAt(1), + decimalSeparator: formatValue({ language, nodeValue: 0.1 }).charAt(1) +}) diff --git a/test/.eslintrc.yaml b/mon-entreprise/test/.eslintrc.yaml similarity index 59% rename from test/.eslintrc.yaml rename to mon-entreprise/test/.eslintrc.yaml index 726568911..d2c0e276e 100644 --- a/test/.eslintrc.yaml +++ b/mon-entreprise/test/.eslintrc.yaml @@ -1,3 +1,3 @@ env: mocha: true - jest: true + jest: true \ No newline at end of file diff --git a/test/companyStatusSelectors.test.js b/mon-entreprise/test/companyStatusSelectors.test.js similarity index 100% rename from test/companyStatusSelectors.test.js rename to mon-entreprise/test/companyStatusSelectors.test.js diff --git a/componentTestSetup.js b/mon-entreprise/test/componentTestSetup.js similarity index 85% rename from componentTestSetup.js rename to mon-entreprise/test/componentTestSetup.js index 45fd41835..e54bf104e 100644 --- a/componentTestSetup.js +++ b/mon-entreprise/test/componentTestSetup.js @@ -7,7 +7,6 @@ chai.use(sinonChai) Enzyme.configure({ adapter: new Adapter() }) // Setup Intl in "en" and "fr" for testing -// var areIntlLocalesSupported = require('intl-locales-supported') // var localesMyAppSupports = ['en', 'fr'] global.Intl = require('intl') diff --git a/test/conversation.test.js b/mon-entreprise/test/conversation.test.js similarity index 54% rename from test/conversation.test.js rename to mon-entreprise/test/conversation.test.js index 8363d04eb..7377325a4 100644 --- a/test/conversation.test.js +++ b/mon-entreprise/test/conversation.test.js @@ -1,6 +1,10 @@ import { expect } from 'chai' -import { getNextQuestions } from '../source/components/utils/useNextQuestion' -import Engine from 'Engine' +import Engine from 'publicodes' +import { + getNextQuestions, + getNextSteps +} from '../source/components/utils/useNextQuestion' +import rules from '../source/rules' describe('conversation', function() { it('should start with the first missing variable', function() { @@ -65,4 +69,60 @@ describe('conversation', function() { ])[0] ).to.equal('cadre') }) + + it('should ask "motif CDD" if "CDD" applies', function() { + const result = Object.keys( + new Engine(rules) + .setSituation({ + 'contrat salarié': 'oui', + 'contrat salarié . CDD': 'oui', + 'contrat salarié . rémunération . brut de base': '2300' + }) + .evaluate('contrat salarié . rémunération . net', { + useDefaultValues: false + }).missingVariables + ) + + expect(result).to.include('contrat salarié . CDD . motif') + }) +}) + +describe('getNextSteps', function() { + it('should give priority to questions that advance most targets', function() { + let missingVariablesByTarget = [ + { + effectif: 34.01, + cadre: 30 + }, + { + cadre: 10.1 + }, + { + effectif: 32.0, + cadre: 10 + } + ] + + let result = getNextSteps(missingVariablesByTarget) + + expect(result[0]).to.equal('cadre') + }) + + it('should give priority to questions by total weight when advancing the same target count', function() { + let missingVariablesByTarget = [ + { + effectif: 24.01, + cadre: 30 + }, + { + effectif: 24.01, + cadre: 10.1 + }, + {} + ] + + let result = getNextSteps(missingVariablesByTarget) + + expect(result[0]).to.equal('effectif') + }) }) diff --git a/test/helpers/browser.js b/mon-entreprise/test/helpers/browser.js similarity index 100% rename from test/helpers/browser.js rename to mon-entreprise/test/helpers/browser.js diff --git a/test/real-rules.test.js b/mon-entreprise/test/real-rules.test.js similarity index 92% rename from test/real-rules.test.js rename to mon-entreprise/test/real-rules.test.js index fdb0460f9..3913c78af 100644 --- a/test/real-rules.test.js +++ b/mon-entreprise/test/real-rules.test.js @@ -1,6 +1,6 @@ import { AssertionError } from 'chai' -import Engine, { parseRules } from 'Engine' -import { disambiguateRuleReference } from 'Engine/ruleUtils' +import Engine, { parseRules } from 'publicodes' +import { disambiguateRuleReference } from '../../publicodes/source/ruleUtils' import rules from 'Rules' // les variables dans les tests peuvent être exprimées relativement à l'espace de nom de la règle, diff --git a/test/regressions/__snapshots__/simulations.jest.js.snap b/mon-entreprise/test/regressions/__snapshots__/simulations.jest.js.snap similarity index 100% rename from test/regressions/__snapshots__/simulations.jest.js.snap rename to mon-entreprise/test/regressions/__snapshots__/simulations.jest.js.snap diff --git a/test/regressions/simulations-artiste-auteur.yaml b/mon-entreprise/test/regressions/simulations-artiste-auteur.yaml similarity index 100% rename from test/regressions/simulations-artiste-auteur.yaml rename to mon-entreprise/test/regressions/simulations-artiste-auteur.yaml diff --git a/test/regressions/simulations-auto-entrepreneur.yaml b/mon-entreprise/test/regressions/simulations-auto-entrepreneur.yaml similarity index 100% rename from test/regressions/simulations-auto-entrepreneur.yaml rename to mon-entreprise/test/regressions/simulations-auto-entrepreneur.yaml diff --git a/test/regressions/simulations-indépendant.yaml b/mon-entreprise/test/regressions/simulations-indépendant.yaml similarity index 100% rename from test/regressions/simulations-indépendant.yaml rename to mon-entreprise/test/regressions/simulations-indépendant.yaml diff --git a/test/regressions/simulations-rémunération-dirigeant.yaml b/mon-entreprise/test/regressions/simulations-rémunération-dirigeant.yaml similarity index 100% rename from test/regressions/simulations-rémunération-dirigeant.yaml rename to mon-entreprise/test/regressions/simulations-rémunération-dirigeant.yaml diff --git a/test/regressions/simulations-salarié.yaml b/mon-entreprise/test/regressions/simulations-salarié.yaml similarity index 100% rename from test/regressions/simulations-salarié.yaml rename to mon-entreprise/test/regressions/simulations-salarié.yaml diff --git a/test/regressions/simulations.jest.js b/mon-entreprise/test/regressions/simulations.jest.js similarity index 98% rename from test/regressions/simulations.jest.js rename to mon-entreprise/test/regressions/simulations.jest.js index 7dbb82f73..dd9a1784f 100644 --- a/test/regressions/simulations.jest.js +++ b/mon-entreprise/test/regressions/simulations.jest.js @@ -6,13 +6,13 @@ // renamed the test configuration may be adapted but the persisted snapshot will remain unchanged). /* eslint-disable no-undef */ -import rules from 'Rules' +import Engine from 'publicodes' +import rules from '../../source/rules' import artisteAuteurConfig from '../../source/components/simulationConfigs/artiste-auteur.yaml' import autoentrepreneurConfig from '../../source/components/simulationConfigs/auto-entrepreneur.yaml' import independantConfig from '../../source/components/simulationConfigs/indépendant.yaml' import remunerationDirigeantConfig from '../../source/components/simulationConfigs/rémunération-dirigeant.yaml' import employeeConfig from '../../source/components/simulationConfigs/salarié.yaml' -import Engine from '../../source/engine' import artisteAuteurSituations from './simulations-artiste-auteur.yaml' import autoEntrepreneurSituations from './simulations-auto-entrepreneur.yaml' import independentSituations from './simulations-indépendant.yaml' diff --git a/test/regressions/styleMock.js b/mon-entreprise/test/regressions/styleMock.js similarity index 100% rename from test/regressions/styleMock.js rename to mon-entreprise/test/regressions/styleMock.js diff --git a/test/unit-translations.test.js b/mon-entreprise/test/unit-translations.test.js similarity index 72% rename from test/unit-translations.test.js rename to mon-entreprise/test/unit-translations.test.js index cee9e820c..6acae6b26 100644 --- a/test/unit-translations.test.js +++ b/mon-entreprise/test/unit-translations.test.js @@ -1,10 +1,10 @@ import { expect } from 'chai' -import { parseRules } from 'Engine' +import { parseRules } from 'publicodes' import { uniq } from 'ramda' -import rawRules from 'Rules' -import unitsTranslations from '../source/locales/units.yaml' +import rawRules from '../source/rules' +import unitsTranslations from '../../publicodes/source/locales/units.yaml' -it('has translation for all base units', () => { +it('use unit that exists in publicode', () => { const rules = parseRules(rawRules) const units = uniq( Object.keys(rules).reduce( diff --git a/mon-entreprise/tsconfig.json b/mon-entreprise/tsconfig.json new file mode 100644 index 000000000..a593bb367 --- /dev/null +++ b/mon-entreprise/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "baseUrl": "source", + "typeRoots": ["source/types"], + "paths": { + "Actions/*": ["actions/*"], + "Components": ["components"], + "Components/*": ["components/*"], + "Images/*": ["images/*"], + "Reducers/*": ["reducers/*"], + "Rules/*": ["rules/*"], + "Rules": ["rules"], + "Selectors/*": ["selectors/*"], + "Types/*": ["types/*"] + } + }, + "include": ["source"] +} diff --git a/source/webpack.common.js b/mon-entreprise/webpack.common.js similarity index 97% rename from source/webpack.common.js rename to mon-entreprise/webpack.common.js index 6b0842372..fbff143ae 100644 --- a/source/webpack.common.js +++ b/mon-entreprise/webpack.common.js @@ -8,9 +8,7 @@ const path = require('path') module.exports.default = { resolve: { alias: { - Engine: path.resolve('source/engine/'), Actions: path.resolve('source/actions/'), - Ui: path.resolve('source/components/ui/'), Components: path.resolve('source/components/'), Selectors: path.resolve('source/selectors/'), Reducers: path.resolve('source/reducers/'), @@ -92,6 +90,8 @@ module.exports.commonLoaders = ({ legacy = false } = {}) => { const babelLoader = { loader: 'babel-loader', options: { + cacheDirectory: true, + rootMode: 'upward', presets: [ [ '@babel/preset-env', @@ -116,7 +116,7 @@ module.exports.commonLoaders = ({ legacy = false } = {}) => { { test: /\.(js|ts|tsx)$/, loader: babelLoader, - exclude: /node_modules|dist/ + exclude: /node_modules(?!\/publicodes)|dist/ }, { test: /\.(jpe?g|png|svg)$/, diff --git a/source/webpack.dev.js b/mon-entreprise/webpack.dev.js similarity index 100% rename from source/webpack.dev.js rename to mon-entreprise/webpack.dev.js diff --git a/source/webpack.prod.js b/mon-entreprise/webpack.prod.js similarity index 98% rename from source/webpack.prod.js rename to mon-entreprise/webpack.prod.js index d230f4ae8..b8bf05afa 100644 --- a/source/webpack.prod.js +++ b/mon-entreprise/webpack.prod.js @@ -91,9 +91,9 @@ module.exports = { navigateFallbackWhitelist: [/^\/[^_]+$/], // fallback for anything that doesn't start with navigateFallbackBlacklist: [ // The service worker should ignore source maps generated by Webpack - /.*.map$/, + /.*\.map$/, /.*\?s=.*$/, - /^\/stats/, + /.*\.worker\.js/, /^\/robots\.txt$/, /^\/sitemap\.infrance\.fr\.txt$/, /^\/sitemap\.infrance\.en\.txt$/ diff --git a/source/webpack.prod.legacyBrowser.js b/mon-entreprise/webpack.prod.legacyBrowser.js similarity index 100% rename from source/webpack.prod.legacyBrowser.js rename to mon-entreprise/webpack.prod.legacyBrowser.js diff --git a/netlify.toml b/netlify.toml index db8e2fd81..52022d8b0 100644 --- a/netlify.toml +++ b/netlify.toml @@ -242,6 +242,12 @@ to = "/mon-entreprise.html" status = 200 +[build] + # Hack while waiting for netlify to support workspace + # https://github.com/netlify/build-image/issues/196 + command = "npm i yarn && yarn && yarn workspace mon-entreprise compile" + publish = "mon-entreprise/dist" + [context.deploy-preview.environment] EN_SITE = "${path}?s=m" FR_SITE = "${path}" diff --git a/package.json b/package.json index 4cc332e56..fa8767c58 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,6 @@ { - "name": "mon-entreprise", - "license": "MIT", - "version": "1.2.8", - "description": "Library to compute the french social security contributions. Also a website that explains the calculations, and a generic engine to build cool forms that asks the question needed to compute an objective.", - "main": "./dist/engine.js", - "files": [ - "dist/engine.js" - ], + "name": "root", + "private": true, "repository": { "type": "git", "url": "https://github.com/betagouv/mon-entreprise.git" @@ -14,107 +8,16 @@ "engines": { "node": ">=12.16.1" }, - "browserslist": [ - "> 1% in FR", - "not ie < 11" - ], - "dependencies": { - "@babel/runtime": "^7.3.4", - "@rehooks/local-storage": "^2.1.1", - "@sentry/browser": "5.15.5", - "classnames": "^2.2.5", - "color-convert": "^1.9.2", - "core-js": "^3.2.1", - "focus-trap-react": "^3.1.2", - "fuse.js": "3.4.1", - "i18next": "^18.0.1", - "iframe-resizer": "^4.1.1", - "js-yaml": "^3.13.1", - "moo": "^0.5.0", - "nearley": "^2.19.0", - "puppeteer": "^2.1.1", - "ramda": "^0.25.0", - "react": "^16.8.6", - "react-color": "^2.14.0", - "react-dom": "npm:@hot-loader/react-dom", - "react-easy-emoji": "^1.4.0", - "react-fuzzy-highlighter": "^0.3.1", - "react-helmet": "^6.0.0", - "react-i18next": "^11.0.0", - "react-loading-skeleton": "^2.0.1", - "react-markdown": "^4.1.0", - "react-monaco-editor": "^0.36.0", - "react-number-format": "^4.3.1", - "react-redux": "^7.0.3", - "react-router": "^5.1.1", - "react-router-dom": "^5.1.1", - "react-router-hash-link": "^1.2.2", - "react-spring": "=8.0.27", - "react-syntax-highlighter": "^10.1.1", - "react-to-print": "^2.5.1", - "recharts": "^1.8.5", - "reduce-reducers": "^1.0.4", - "redux": "^4.0.4", - "redux-sentry-middleware": "^0.1.8", - "redux-thunk": "^2.3.0", - "regenerator-runtime": "^0.13.3", - "reselect": "^4.0.0", - "swr": "^0.1.16", - "whatwg-fetch": "^3.0.0", - "yaml": "^1.9.2" - }, - "scripts": { - "prepare": "node source/scripts/prepare.js", - "compile": "yarn run webpack --config source/webpack.prod.js && yarn run webpack --config source/webpack.prod.legacyBrowser.js", - "simple-compile": "yarn run webpack --config source/webpack.prod.js", - "stats": "webpack --config source/webpack.prod.js --profile --json > stats.json", - "eslintrc-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check", - "eslint-check": "eslint . --ext .js,.jsx,.ts,.tsx", - "prettier-check": "prettier --check \"{source,test,cypress}/**/*.{js,jsx,ts,tsx}\"", - "lint": "yarn eslintrc-check && yarn eslint-check && yarn prettier-check", - "type-check": "tsc --noEmit", - "externalize": "node source/scripts/externalize.js", - "analyze-bundle": "ANALYZE_BUNDLE=1 yarn run compile", - "heroku-postbuild": "yarn install --production=false && yarn compile", - "start": "node source/server.js", - "test-inversions": "yarn test-watch --grep 'inversions'", - "test-meca": "yarn test-watch --grep 'Mécanismes'", - "test-rules": "yarn test-watch --grep 'notre base de règles'", - "test-cypress": "yarn run cypress run", - "test-watch": "yarn test-common --watch", - "test-common": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js \"./{,!(node_modules)/**/}!(webpack).test.js\"", - "test": "yarn test-common", - "test-one": "yarn mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js", - "test-components": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage ---require test/helpers/browser.js \"source/components/**/*.test.js\" --watch", - "test-lib": "mocha-webpack --webpack-config source/webpack.lib.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage test/library.test.js", - "test-expressions": "yarn test-common --grep 'Suite expressions'", - "test-units": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js test/units.test.js", - "test-regressions": "jest", - "test-bundlesize": "bundlesize", - "compile-lib": "yarn webpack --config source/webpack.lib.js", - "compile-dev": "FR_SITE='http://localhost:5000${path}' EN_SITE='http://localhost:5001${path}' yarn run compile", - "i18n:rules:check": "node source/scripts/i18n/check-missing-rule-translation.js", - "i18n:rules:translate": "node source/scripts/i18n/translate-rules.js", - "i18n:ui:check": "yarn run i18next && node source/scripts/i18n/check-missing-UI-translation", - "i18n:ui:translate": "rm -rf source/locales/static-analysis-fr.json && yarn run i18next && node source/scripts/i18n/translate-ui.js", - "publicodes:serve": "PORT=5002 serve --config serve.publicodes.json --no-clipboard", - "publicodes:test-dev": "cypress open --browser chromium --config baseUrl=http://localhost:8080/publicodes,integrationFolder=cypress/integration/publi.codes", - "mon-entreprise:serve": "PORT=5000 serve --config serve.mon-entreprise.json --no-clipboard", - "mon-entreprise:test-dev": "cypress open --browser chromium", - "mycompanyinfrance:serve": "PORT=5001 serve --config serve.infrance.json --no-clipboard", - "mycompanyinfrance:test-dev": "cypress open --browser chromium --config baseUrl=http://localhost:8080/infrance", - "serve-dev": "yarn run mon-entreprise:serve & yarn run mycompanyinfrance:serve & yarn run publicodes:serve" - }, "devDependencies": { - "@babel/core": "^7.6.4", - "@babel/plugin-proposal-class-properties": "^7.1.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/preset-env": "^7.6.3", - "@babel/preset-react": "^7.0.0", - "@babel/preset-typescript": "^7.6.0", + "@babel/core": "^7.9.0", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.5", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/preset-env": "^7.9.5", + "@babel/preset-react": "^7.9.4", + "@babel/preset-typescript": "^7.9.0", "@types/cheerio": "^0.22.18", "@types/classnames": "^2.2.9", "@types/color-convert": "^1.9.0", @@ -130,10 +33,8 @@ "@types/react-color": "^3.0.1", "@types/react-dom": "^16.9.3", "@types/react-helmet": "^5.0.13", - "@types/react-highlight-words": "^0.16.0", "@types/react-redux": "^7.1.5", "@types/react-router": "^5.1.2", - "@types/react-router-dom": "^5.1.0", "@types/react-router-hash-link": "^1.2.1", "@types/react-syntax-highlighter": "^11.0.4", "@types/recharts": "^1.8.9", @@ -142,24 +43,21 @@ "@types/webpack-bundle-analyzer": "^2.13.3", "@types/webpack-env": "^1.14.1", "@types/workbox-webpack-plugin": "^5.1.0", - "@typescript-eslint/eslint-plugin": "^2.29.0", - "@typescript-eslint/parser": "^2.29.0", - "akh": "^3.1.2", - "autoprefixer": "^9.3.1", + "@typescript-eslint/eslint-plugin": "^2.31.0", + "@typescript-eslint/parser": "^2.31.0", + "autoprefixer": "^9.7.6", "babel-eslint": "^11.0.0-beta.0", "babel-jest": "^24.9.0", "babel-loader": "^8.0.2", - "babel-plugin-ramda": "^1.6.3", + "babel-plugin-ramda": "^2.0.0", "babel-plugin-styled-components": "^1.10.7", "babel-plugin-webpack-alias": "^2.1.2", "bundlesize": "^0.18.0", "chai": "^4.1.2", - "co-request": "^1.0.0", "connect-history-api-fallback": "^1.5.0", "copy-webpack-plugin": "^4.5.2", "css-loader": "^0.28.11", "csv-loader": "^2.1.1", - "daggy": "^1.3.0", "dedent-js": "^1.0.1", "dotenv": "=8.1.0", "enzyme": "^3.3.0", @@ -173,7 +71,6 @@ "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", "http-server": "^0.11.1", - "i18next-parser": "https://github.com/i18next/i18next-parser#master", "intl": "^1.2.5", "intl-locales-supported": "^1.0.0", "isomorphic-fetch": "^2.2.1", @@ -182,7 +79,6 @@ "jest-transform-nearley": "^1.0.0", "jsdom": "^12.0.0", "json-loader": "^0.5.7", - "koa-connect": "^2.0.1", "mini-css-extract-plugin": "^0.4.4", "mocha": "^5.0.4", "mocha-webpack": "^2.0.0-beta.0", @@ -191,16 +87,13 @@ "nearley-loader": "^2.0.0", "postcss-loader": "^2.1.2", "prettier": "^1.19.1", - "ramda-fantasy": "^0.8.0", "raw-loader": "^0.5.1", - "react-hot-loader": "^4.12.21", + "react-hot-loader": "^4.12.15", "serve": "^11.1.0", - "serve-handler": "^6.1.1", "sinon": "^4.5.0", "sinon-chai": "^3.0.0", "source-map-support": "^0.5.4", "style-loader": "^0.23.1", - "styled-components": "^5.1.0", "toml-loader": "^1.0.0", "typescript": "^3.8.3", "url-loader": "^1.0.1", @@ -218,7 +111,22 @@ "cypress": "^3.6.1", "prerender-spa-plugin": "^3.4.0" }, - "resolutions": { - "react-fuzzy-highlighter/**/fuse.js": "3.4.1" - } + "scripts": { + "lint:eslintrc": "eslint --print-config .eslintrc.js | eslint-config-prettier-check", + "lint:eslint": "eslint . --ext .js,.jsx,.ts,.tsx", + "lint:eslint:fix": "yarn lint:eslint --fix", + "lint:prettier": "yarn workspaces run prettier --check \"{source,test,cypress}/**/*.{js,jsx,ts,tsx}\"", + "lint:prettier:fix": "yarn lint:prettier --write", + "lint:fix": "yarn lint:eslint:fix && yarn lint:prettier:fix", + "lint": "yarn lint:eslintrc && yarn lint:eslint && yarn lint:prettier", + "test": "yarn workspaces run test", + "prepare": "yarn workspace mon-entreprise run prepare", + "test:type": "yarn workspaces run tsc --noEmit", + "test:regressions": "jest", + "link:publicodes": "yarn workspace publicodes link && yarn workspace mon-entreprise link publicodes" + }, + "workspaces": [ + "mon-entreprise", + "publicodes" + ] } diff --git a/source/engine/README.md b/publicodes/README.md similarity index 100% rename from source/engine/README.md rename to publicodes/README.md diff --git a/publicodes/package.json b/publicodes/package.json new file mode 100644 index 000000000..b29e06fc0 --- /dev/null +++ b/publicodes/package.json @@ -0,0 +1,32 @@ +{ + "name": "publicodes", + "version": "1.0.0", + "description": "A declarative language for encoding public algorithm", + "main": "source/index.ts", + "repository": { + "type": "git", + "url": "https://github.com/betagouv/mon-entreprise.git", + "directory": "publicodes" + }, + "license": "MIT", + "private": false, + "dependencies": { + "classnames": "^2.2.6", + "moo": "^0.5.1", + "nearley": "^2.19.2", + "ramda": "^0.27.0", + "react-easy-emoji": "^1.4.0", + "react-i18next": "^11.4.0", + "react-markdown": "^4.3.1", + "yaml": "^1.9.2" + }, + "peerDependencies": { + "react": "^16.13.1", + "react-router-dom": "^5.1.1", + "react-router-hash-link": "^1.2.2" + }, + "scripts": { + "test:file": "yarn mocha-webpack --webpack-config ../webpack.test.js --include test/setupIntl.js --require source-map-support/register ", + "test": "yarn test:file \"./{,!(node_modules)/**/}!(webpack).test.js\"" + } +} diff --git a/publicodes/source/components/Markdown.tsx b/publicodes/source/components/Markdown.tsx new file mode 100644 index 000000000..19c50bc85 --- /dev/null +++ b/publicodes/source/components/Markdown.tsx @@ -0,0 +1,72 @@ +import React, { useContext } from 'react' +import emoji from 'react-easy-emoji' +import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown' +import { HashLink as Link } from 'react-router-hash-link' +import { EngineContext } from './contexts' +import { RuleLinkWithContext } from './RuleLink' + +const internalURLs = { + 'mon-entreprise.fr': 'mon-entreprise', + 'mycompanyinfrance.fr': 'infrance', + 'publi.codes': 'publicodes' +} as const + +export function LinkRenderer({ + href, + children, + ...otherProps +}: Omit, 'ref'>) { + const engine = useContext(EngineContext) + if (!engine) { + throw new Error('an engine should be provided in context') + } + const rules = engine.getParsedRules() + + if (href && rules[href]) { + return ( + + {children} + + ) + } + + if (href && !href.startsWith('http')) { + return ( + + {children} + + ) + } + + return ( + + {children} + + ) +} +const TextRenderer = ({ children }: { children: string }) => ( + <>{emoji(children)} +) + +type MarkdownProps = ReactMarkdownProps & { + source: string | undefined + className?: string +} + +export const Markdown = ({ + source, + className = '', + renderers = {}, + ...otherProps +}: MarkdownProps) => ( + +) diff --git a/publicodes/source/components/RuleLink.tsx b/publicodes/source/components/RuleLink.tsx new file mode 100644 index 000000000..92dd03d3a --- /dev/null +++ b/publicodes/source/components/RuleLink.tsx @@ -0,0 +1,62 @@ +import React, { useContext } from 'react' +import emoji from 'react-easy-emoji' +import { Link } from 'react-router-dom' +import Engine from '..' +import { encodeRuleName } from '../ruleUtils' +import { + BasepathContext, + EngineContext, + UseDefaultValuesContext +} from './contexts' + +type RuleLinkProps = Omit< + React.ComponentProps, + 'to' +> & { + dottedName: Name + engine: Engine + documentationPath: string + displayIcon?: boolean + useDefaultValues?: boolean + children?: React.ReactNode +} + +export function RuleLink({ + dottedName, + engine, + documentationPath, + displayIcon = false, + useDefaultValues = false, + children, + ...props +}: RuleLinkProps) { + const rule = engine.getParsedRules()[dottedName] + const newPath = documentationPath + '/' + encodeRuleName(dottedName) + + return ( + + {children || rule.title}{' '} + {displayIcon && rule.icons && {emoji(rule.icons)} } + + ) +} + +export function RuleLinkWithContext( + props: Omit, 'engine' | 'documentationPath'> +) { + const engine = useContext(EngineContext) + if (!engine) { + throw new Error('an engine should be provided in context') + } + const documentationPath = useContext(BasepathContext) + const useDefaultValues = useContext(UseDefaultValuesContext) + + return ( + + ) +} diff --git a/publicodes/source/components/contexts.tsx b/publicodes/source/components/contexts.tsx new file mode 100644 index 000000000..606a1355d --- /dev/null +++ b/publicodes/source/components/contexts.tsx @@ -0,0 +1,6 @@ +import { createContext } from 'react' +import Engine from '..' + +export const UseDefaultValuesContext = createContext(true) +export const BasepathContext = createContext('/documentation') +export const EngineContext = createContext | null>(null) diff --git a/publicodes/source/components/index.tsx b/publicodes/source/components/index.tsx new file mode 100644 index 000000000..0dce0e271 --- /dev/null +++ b/publicodes/source/components/index.tsx @@ -0,0 +1,64 @@ +import React, { useEffect } from 'react' +import { Route, useLocation } from 'react-router-dom' +import Engine from '..' +import i18n from '../i18n' +import { decodeRuleName, encodeRuleName } from '../ruleUtils' +import { + BasepathContext, + EngineContext, + UseDefaultValuesContext +} from './contexts' +import RulePage from './rule/Rule' + +export { RuleLink } from './RuleLink' + +type DocumentationProps = { + documentationPath: string + engine: Engine + language: 'fr' | 'en' +} + +export function Documentation({ + documentationPath, + engine, + language = 'fr' +}: DocumentationProps) { + useEffect(() => { + if (language !== i18n.language) { + i18n.changeLanguage(language) + } + }, [language]) + const state: { useDefaultValues?: boolean } = useLocation().state ?? {} + const useDefaultValues = + ('useDefaultValues' in state && state.useDefaultValues) || false + return ( + + + + { + return ( + + ) + }} + /> + + + + ) +} + +export function getDocumentationSiteMap({ engine, documentationPath }) { + return Object.fromEntries( + Object.keys(engine.getParsedRules()).map(dottedName => [ + documentationPath + '/' + encodeRuleName(dottedName), + dottedName + ]) + ) +} diff --git a/source/engine/mecanismViews/Allègement.js b/publicodes/source/components/mecanisms/Allègement.js similarity index 97% rename from source/engine/mecanismViews/Allègement.js rename to publicodes/source/components/mecanisms/Allègement.js index 010de66b6..6caeee0cd 100644 --- a/source/engine/mecanismViews/Allègement.js +++ b/publicodes/source/components/mecanisms/Allègement.js @@ -1,6 +1,6 @@ import { map, mapObjIndexed, values } from 'ramda' import React from 'react' -import { makeJsx } from '../evaluation' +import { makeJsx } from '../../evaluation' import { Node } from './common' export default function Allègement({ nodeValue, explanation: rawExplanation }) { diff --git a/source/engine/mecanismViews/Barème.css b/publicodes/source/components/mecanisms/Barème.css similarity index 100% rename from source/engine/mecanismViews/Barème.css rename to publicodes/source/components/mecanisms/Barème.css diff --git a/source/engine/mecanismViews/Barème.tsx b/publicodes/source/components/mecanisms/Barème.tsx similarity index 97% rename from source/engine/mecanismViews/Barème.tsx rename to publicodes/source/components/mecanisms/Barème.tsx index 1089514b8..be857d451 100644 --- a/source/engine/mecanismViews/Barème.tsx +++ b/publicodes/source/components/mecanisms/Barème.tsx @@ -1,10 +1,10 @@ import classNames from 'classnames' import React from 'react' import { Trans } from 'react-i18next' -import { makeJsx } from '../evaluation' +import { makeJsx } from '../../evaluation' import './Barème.css' import { Node, NodeValuePointer } from './common' -import { parseUnit } from 'Engine/units' +import { parseUnit } from '../../units' export default function Barème({ nodeValue, explanation, unit }) { return ( diff --git a/source/engine/mecanismViews/Composantes.css b/publicodes/source/components/mecanisms/Composantes.css similarity index 100% rename from source/engine/mecanismViews/Composantes.css rename to publicodes/source/components/mecanisms/Composantes.css diff --git a/source/engine/mecanismViews/Composantes.js b/publicodes/source/components/mecanisms/Composantes.js similarity index 69% rename from source/engine/mecanismViews/Composantes.js rename to publicodes/source/components/mecanisms/Composantes.js index 2db414667..632a88229 100644 --- a/source/engine/mecanismViews/Composantes.js +++ b/publicodes/source/components/mecanisms/Composantes.js @@ -1,9 +1,9 @@ -import colors from 'Engine/mecanismViews/colors' import { toPairs } from 'ramda' import React from 'react' import { Trans, useTranslation } from 'react-i18next' +import { makeJsx } from '../../evaluation' import writtenNumbers from '../../locales/writtenNumbers.yaml' -import { makeJsx } from '../evaluation' +import colors from './colors' import { InlineMecanism, Node } from './common' import './Composantes.css' @@ -19,30 +19,30 @@ export default function Composantes({ nodeValue, explanation, unit }) { unit={unit} > <> -

+

La somme de{' '} {writtenNumbers[i18n.language][explanation.length]}{' '} :

    {explanation.map((c, i) => [ -
  1. +
    • {toPairs(c.composante).map(([k, v]) => (
    • {k}:{' '} @@ -54,12 +54,12 @@ export default function Composantes({ nodeValue, explanation, unit }) {
    {makeJsx(c)}
    {i === explanation.length - 1 ? null : '+'}
    diff --git a/source/engine/mecanismViews/Grille.tsx b/publicodes/source/components/mecanisms/Grille.tsx similarity index 100% rename from source/engine/mecanismViews/Grille.tsx rename to publicodes/source/components/mecanisms/Grille.tsx diff --git a/source/engine/mecanismViews/InversionNumérique.css b/publicodes/source/components/mecanisms/InversionNumérique.css similarity index 100% rename from source/engine/mecanismViews/InversionNumérique.css rename to publicodes/source/components/mecanisms/InversionNumérique.css diff --git a/source/engine/mecanismViews/InversionNumérique.js b/publicodes/source/components/mecanisms/InversionNumérique.js similarity index 96% rename from source/engine/mecanismViews/InversionNumérique.js rename to publicodes/source/components/mecanisms/InversionNumérique.js index 31455db22..213c08ce3 100644 --- a/source/engine/mecanismViews/InversionNumérique.js +++ b/publicodes/source/components/mecanisms/InversionNumérique.js @@ -1,5 +1,5 @@ -import { makeJsx } from 'Engine/evaluation' import React from 'react' +import { makeJsx } from '../../evaluation' import { Node } from './common' import './InversionNumérique.css' diff --git a/source/engine/mecanismViews/Product.js b/publicodes/source/components/mecanisms/Product.js similarity index 97% rename from source/engine/mecanismViews/Product.js rename to publicodes/source/components/mecanisms/Product.js index 13179759c..29f7e6f96 100644 --- a/source/engine/mecanismViews/Product.js +++ b/publicodes/source/components/mecanisms/Product.js @@ -1,6 +1,6 @@ -import { makeJsx } from 'Engine/evaluation' import React from 'react' import { Trans } from 'react-i18next' +import { makeJsx } from '../../evaluation' import { Node } from './common' import './InversionNumérique.css' diff --git a/source/engine/mecanismViews/Recalcul.tsx b/publicodes/source/components/mecanisms/Recalcul.tsx similarity index 57% rename from source/engine/mecanismViews/Recalcul.tsx rename to publicodes/source/components/mecanisms/Recalcul.tsx index 3728b2cf5..b18cfa362 100644 --- a/source/engine/mecanismViews/Recalcul.tsx +++ b/publicodes/source/components/mecanisms/Recalcul.tsx @@ -1,8 +1,7 @@ -import RuleLink from 'Components/RuleLink' -import { makeJsx } from 'Engine/evaluation' +import { RuleLinkWithContext } from '../RuleLink' +import { makeJsx } from '../../evaluation' import React from 'react' import { Trans } from 'react-i18next' -import { DottedName } from 'Rules' import { Node } from './common' export default function Recalcul({ nodeValue, explanation }) { @@ -17,21 +16,14 @@ export default function Recalcul({ nodeValue, explanation }) { {explanation.recalcul && ( Recalcul de la règle{' '} - avec les - valeurs suivantes : + {' '} + avec les valeurs suivantes : )}
      {Object.keys(explanation.amendedSituation).map(dottedName => ( -
    • - ={' '} +
    • + ={' '} {makeJsx(explanation.amendedSituation[dottedName])}
    • ))} diff --git a/source/engine/mecanismViews/Somme.css b/publicodes/source/components/mecanisms/Somme.css similarity index 89% rename from source/engine/mecanismViews/Somme.css rename to publicodes/source/components/mecanisms/Somme.css index b10a4bb2f..9d438d097 100644 --- a/source/engine/mecanismViews/Somme.css +++ b/publicodes/source/components/mecanisms/Somme.css @@ -90,26 +90,16 @@ flex: 1; max-width: 100%; display: flex; - align-items: center; + align-items: baseline; padding: 0.1em 0.4em; padding-top: 0.2em; overflow: hidden; } .mecanism-somme__row .element .unfoldIndication { text-transform: capitalize; - font-size: 90%; - align-self: baseline; flex: 1; + margin-left: 0.6rem; text-align: left; - color: rgb(51, 51, 80); -} - -.somme > :not(.mecanism-somme__table) .element .unfoldIndication { - font-size: 60%; - color: #888; - cursor: pointer; - font-weight: 400; - white-space: nowrap; } .mecanism-somme__row .value { @@ -124,7 +114,6 @@ overflow: hidden; text-overflow: ellipsis; max-width: 100%; - display: inline-block; } .mecanism-somme__row .element .situationValue { diff --git a/source/engine/mecanismViews/Somme.js b/publicodes/source/components/mecanisms/Somme.js similarity index 92% rename from source/engine/mecanismViews/Somme.js rename to publicodes/source/components/mecanisms/Somme.js index 7995dfb5a..4dccc11b1 100644 --- a/source/engine/mecanismViews/Somme.js +++ b/publicodes/source/components/mecanisms/Somme.js @@ -1,6 +1,6 @@ import { path } from 'ramda' import React, { useState } from 'react' -import { makeJsx } from '../evaluation' +import { makeJsx } from '../../evaluation' import { Node, NodeValuePointer } from './common' import './Somme.css' @@ -37,7 +37,7 @@ function Row({ v, i, unit }) {
      {makeJsx(v)} {isSomme && ( - )} diff --git a/source/engine/mecanismViews/TauxProgressif.tsx b/publicodes/source/components/mecanisms/TauxProgressif.tsx similarity index 100% rename from source/engine/mecanismViews/TauxProgressif.tsx rename to publicodes/source/components/mecanisms/TauxProgressif.tsx diff --git a/source/engine/mecanismViews/Variations.css b/publicodes/source/components/mecanisms/Variations.css similarity index 100% rename from source/engine/mecanismViews/Variations.css rename to publicodes/source/components/mecanisms/Variations.css diff --git a/source/engine/mecanismViews/Variations.js b/publicodes/source/components/mecanisms/Variations.js similarity index 94% rename from source/engine/mecanismViews/Variations.js rename to publicodes/source/components/mecanisms/Variations.js index 6f805ca69..7f67d0e68 100644 --- a/source/engine/mecanismViews/Variations.js +++ b/publicodes/source/components/mecanisms/Variations.js @@ -3,7 +3,7 @@ import React, { useState } from 'react' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import writtenNumbers from '../../locales/writtenNumbers.yaml' -import { makeJsx } from '../evaluation' +import { makeJsx } from '../../evaluation' import { InlineMecanism, Node } from './common' import './Variations.css' @@ -20,8 +20,8 @@ export default function Variations({ nodeValue, explanation, unit }) { > {' '} <> -

      - {writtenNumbers[i18n.language][explanation.length]} +

      + {writtenNumbers[i18n.language][explanation.length]} :

        diff --git a/publicodes/source/components/mecanisms/colors.js b/publicodes/source/components/mecanisms/colors.js new file mode 100644 index 000000000..e39d8cc3e --- /dev/null +++ b/publicodes/source/components/mecanisms/colors.js @@ -0,0 +1,14 @@ +const colors = { + ruleProp: '#9b59b6', + 'applicable si': '#9b59b6', + 'non applicable si': '#9b59b6', + produit: '#2ecc71', + 'une de ces conditions': '#3498db', + 'toutes ces conditions': '#3498db', + composantes: '#3498db', + variations: '#FF9800', + 'taux progressif': '#795548', + barème: '#607D8B', + grille: '#AD1457' +} +export default name => colors[name] || '#34495e' diff --git a/source/engine/mecanismViews/colors.ts b/publicodes/source/components/mecanisms/colors.ts similarity index 100% rename from source/engine/mecanismViews/colors.ts rename to publicodes/source/components/mecanisms/colors.ts diff --git a/source/engine/mecanismViews/common.tsx b/publicodes/source/components/mecanisms/common.tsx similarity index 54% rename from source/engine/mecanismViews/common.tsx rename to publicodes/source/components/mecanisms/common.tsx index 6c75ffcbd..91dfa8e7c 100644 --- a/source/engine/mecanismViews/common.tsx +++ b/publicodes/source/components/mecanisms/common.tsx @@ -1,20 +1,12 @@ import { default as classNames, default as classnames } from 'classnames' -import { UseDefaultValuesContext } from 'Components/Documentation/UseDefaultValuesContext' -import { SitePathsContext } from 'Components/utils/SitePathsContext' -import { formatValue } from 'Engine/format' -import { ParsedRule, Types, Evaluation } from 'Engine/types' -import { contains, isNil, pipe, sort, toPairs } from 'ramda' -import React, { useContext } from 'react' +import { contains, isNil } from 'ramda' +import React from 'react' import { Trans } from 'react-i18next' -import { useSelector } from 'react-redux' -import { Link } from 'react-router-dom' -import { DottedName } from 'Rules' -import { LinkButton } from 'Ui/Button' +import { formatValue } from '../../format' +import { Evaluation, ParsedRule, Types, Unit } from '../../types' import { capitalise0 } from '../../utils' -import { encodeRuleName } from '../ruleUtils' +import { RuleLinkWithContext } from '../RuleLink' import mecanismColors from './colors' -import { EngineContext } from 'Components/utils/EngineContext' -import { Unit } from 'Engine/units' type NodeValuePointerProps = { data: Evaluation @@ -26,15 +18,16 @@ export const NodeValuePointer = ({ data, unit }: NodeValuePointerProps) => ( className={classnames('situationValue', { boolean: typeof data == 'boolean' })} - css={` - background: white; - border-bottom: 0 !important; - padding: 0 0.2rem; - text-decoration: none !important; - box-shadow: 2px 2px 4px 1px #d9d9d9, 0 0 0 1px #d9d9d9; - line-height: 1.6em; - border-radius: 0.2rem; - `} + style={{ + background: 'white', + borderBottom: '0 !important', + marginLeft: '0.4rem', + padding: '0 0.2rem', + textDecoration: 'none !important', + boxShadow: '2px 2px 4px 1px #d9d9d9, 0 0 0 1px #d9d9d9', + lineHeight: '1.6em', + borderRadius: '0.2rem' + }} > {formatValue({ nodeValue: data, unit, language: 'fr' })} @@ -66,22 +59,21 @@ export function Node({ style={termDefinition ? { borderColor: mecanismColors(name) } : {}} > {name && !inline && ( - )} {children}{' '} {name ? ( !isNil(value) && (
        - = - + =
        ) ) : ( @@ -99,13 +91,13 @@ export function Node({ export function InlineMecanism({ name }: { name: string }) { return ( - {name} - + ) } @@ -120,54 +112,18 @@ type LeafProps = { // Un élément du graphe de calcul qui a une valeur interprétée (à afficher) export function Leaf({ className, rule, nodeValue, filter, unit }: LeafProps) { - const sitePaths = useContext(SitePathsContext) - const useDefaultValues = useContext(UseDefaultValuesContext) const title = rule.title || capitalise0(rule.name) return ( - + {rule.acronyme ? {rule.acronyme} : title}{' '} {filter} - - {!isNil(nodeValue) && ( - - - - )} + + {!isNil(nodeValue) && } ) } - -type SimpleRuleLinkProps = { rule: ParsedRule } - -export function SimpleRuleLink({ - rule: { dottedName, title, name } -}: SimpleRuleLinkProps) { - return ( - - {title || capitalise0(name)} - - ) -} - -export const sortObjectByKeys = pipe( - toPairs as any, - // we don't rely on the sorting of objects - sort(([k1]: [number], [k2]: [number]) => k1 - k2) -) diff --git a/source/components/Documentation/Algorithm.css b/publicodes/source/components/rule/Algorithm.css similarity index 96% rename from source/components/Documentation/Algorithm.css rename to publicodes/source/components/rule/Algorithm.css index 4eab61bdc..ff6ac7169 100644 --- a/source/components/Documentation/Algorithm.css +++ b/publicodes/source/components/rule/Algorithm.css @@ -43,11 +43,9 @@ .mecanism > .nodeHead { border-color: inherit; -} -.mecanism > .nodeHead .name { - position: absolute; - top: 0; - left: 0; + margin-top: -1rem; + margin-left: -1rem; + margin-bottom: 0.4rem; } .inlineMecanism .name, .mecanism > .nodeHead .name { @@ -134,9 +132,9 @@ flex: 1; } .mecanism-result { - position: absolute; - bottom: 0px; - right: 0; + position: relative; + bottom: calc(-1rem + 2px); + text-align: right; } .mecanism .mecanism { flex: initial; diff --git a/source/components/Documentation/Algorithm.tsx b/publicodes/source/components/rule/Algorithm.tsx similarity index 91% rename from source/components/Documentation/Algorithm.tsx rename to publicodes/source/components/rule/Algorithm.tsx index 7e0dd3f4c..a520f8017 100644 --- a/source/components/Documentation/Algorithm.tsx +++ b/publicodes/source/components/rule/Algorithm.tsx @@ -1,9 +1,9 @@ -import { makeJsx } from 'Engine/evaluation' import { any, identity, path } from 'ramda' import React from 'react' import { Trans } from 'react-i18next' +import { EvaluatedRule } from '../../types' +import { makeJsx } from '../../evaluation' import './Algorithm.css' -import { EvaluatedRule, ParsedRule } from 'Rules' const Conditions = ({ 'rendu non applicable': disabledBy, @@ -32,19 +32,19 @@ const Conditions = ({ ] return any(identity, listElements) ? ( -
        + <>

        Déclenchement

          {listElements}
        -
        + ) : null } function ShowIfDisabled({ dependency }: { dependency: EvaluatedRule }) { return (
      1. - + Désactivée {' '} car dépend de {makeJsx(dependency)} diff --git a/source/components/Documentation/Examples.js b/publicodes/source/components/rule/Examples.js similarity index 100% rename from source/components/Documentation/Examples.js rename to publicodes/source/components/rule/Examples.js diff --git a/publicodes/source/components/rule/Header.css b/publicodes/source/components/rule/Header.css new file mode 100644 index 000000000..d073de922 --- /dev/null +++ b/publicodes/source/components/rule/Header.css @@ -0,0 +1,16 @@ +.rule-header { + padding: 1rem; +} +.rule-header__breadcrumb { + margin: 0; + padding: 0; +} + +.rule-header__breadcrumb > li { + display: inline; + padding: 0; +} + +.rule-header__title { + margin: 0.6rem 0; +} diff --git a/publicodes/source/components/rule/Header.tsx b/publicodes/source/components/rule/Header.tsx new file mode 100644 index 000000000..423c3e952 --- /dev/null +++ b/publicodes/source/components/rule/Header.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import { ruleParents } from '../../ruleUtils' +import './Header.css' +import { RuleLinkWithContext } from '../RuleLink' + +export default function RuleHeader({ dottedName }) { + return ( +
        +
          + {ruleParents(dottedName) + .reverse() + .map(parentDottedName => ( +
        • + + {' › '} +
        • + ))} +
        {' '} +

        + +

        +
        + ) +} diff --git a/source/components/Documentation/References.css b/publicodes/source/components/rule/References.css similarity index 100% rename from source/components/Documentation/References.css rename to publicodes/source/components/rule/References.css diff --git a/source/components/Documentation/References.tsx b/publicodes/source/components/rule/References.tsx similarity index 82% rename from source/components/Documentation/References.tsx rename to publicodes/source/components/rule/References.tsx index 580d5941b..294290adc 100644 --- a/source/components/Documentation/References.tsx +++ b/publicodes/source/components/rule/References.tsx @@ -1,4 +1,4 @@ -import references from 'Images/références/références.yaml' +import references from './références/références.yaml' import { toPairs } from 'ramda' import React from 'react' import { capitalise0 } from '../../utils' @@ -24,23 +24,23 @@ function Ref({ name, link }: RefProps) { domain = cleanDomain(link) return (
      2. {refData.image && ( - + )} {capitalise0(name)} diff --git a/publicodes/source/components/rule/Rule.tsx b/publicodes/source/components/rule/Rule.tsx new file mode 100644 index 000000000..83a08bd91 --- /dev/null +++ b/publicodes/source/components/rule/Rule.tsx @@ -0,0 +1,142 @@ +import React, { useState } from 'react' +import { Trans } from 'react-i18next' +import Engine from '../..' +import { formatValue } from '../../format' +import mecanisms from '../../mecanisms.yaml' +import { serializeUnit } from '../../units' +import { Markdown } from '../Markdown' +import { RuleLinkWithContext } from '../RuleLink' +import Algorithm from './Algorithm' +import RuleHeader from './Header' +import References from './References' + +// let LazySource = React.lazy(() => import('../../../../mon-entreprise/source/components/RuleSource')) + +export default function Rule({ + dottedName, + useDefaultValues, + engine, + language +}) { + const rule = engine.evaluate(dottedName, { + useDefaultValues + }) + const [viewSource, setViewSource] = useState(false) + const { description, question } = rule + + return ( +
        + +
        + +
        + + {(rule.nodeValue || rule.defaultValue || rule.unit) && ( + <> +

        + {rule.nodeValue != null && ( + <> + {formatValue({ ...rule, language })} +
        + + )} + {rule.defaultValue?.nodeValue != null && ( + <> + + Valeur par défaut :{' '} + {formatValue({ + ...rule.defaultValue, + language + })} + +
        + + )} + {rule.nodeValue == null && !rule.defaultValue?.unit && rule.unit && ( + <> + Unité : {serializeUnit(rule.unit)} + + )} +

        + + )} + + + + {rule['rend non applicable'] && ( + <> +

        + Rend non applicable les règles suivantes :{' '} +

        +
          + {rule['rend non applicable'].map(ruleName => ( +
        • + +
        • + ))} +
        + + )} + {rule.note && ( + <> +

        Note

        +
        + +
        + + )} + {rule.références && ( + <> +

        + Références +

        + + + )} + {/* */} + + +
        + ) +} + +function AssociatedRules({ + dottedName, + engine +}: { + dottedName: Name + engine: Engine +}) { + const namespaceRules = Object.keys(engine.getParsedRules()).filter( + ruleDottedName => + ruleDottedName.startsWith(dottedName) && + ruleDottedName.split(' . ').length === dottedName.split(' . ').length + 1 + ) + if (!namespaceRules.length) { + return null + } + return ( +
        +

        + Pages associées +

        +
          + {namespaceRules.map(dottedName => ( +
        • + +
        • + ))} +
        +
        + ) +} diff --git a/source/images/références/URSSAF.png b/publicodes/source/components/rule/références/URSSAF.png similarity index 100% rename from source/images/références/URSSAF.png rename to publicodes/source/components/rule/références/URSSAF.png diff --git a/source/images/références/agirc-arrco.png b/publicodes/source/components/rule/références/agirc-arrco.png similarity index 100% rename from source/images/références/agirc-arrco.png rename to publicodes/source/components/rule/références/agirc-arrco.png diff --git a/source/images/références/ameli.png b/publicodes/source/components/rule/références/ameli.png similarity index 100% rename from source/images/références/ameli.png rename to publicodes/source/components/rule/références/ameli.png diff --git a/source/images/références/bpi-création.png b/publicodes/source/components/rule/références/bpi-création.png similarity index 100% rename from source/images/références/bpi-création.png rename to publicodes/source/components/rule/références/bpi-création.png diff --git a/source/images/références/ladocumentationfrançaise.png b/publicodes/source/components/rule/références/ladocumentationfrançaise.png similarity index 100% rename from source/images/références/ladocumentationfrançaise.png rename to publicodes/source/components/rule/références/ladocumentationfrançaise.png diff --git a/source/images/références/marianne.png b/publicodes/source/components/rule/références/marianne.png similarity index 100% rename from source/images/références/marianne.png rename to publicodes/source/components/rule/références/marianne.png diff --git a/source/sites/mon-entreprise.fr/pages/integration/images/pole-emploi.png b/publicodes/source/components/rule/références/pole-emploi.png similarity index 100% rename from source/sites/mon-entreprise.fr/pages/integration/images/pole-emploi.png rename to publicodes/source/components/rule/références/pole-emploi.png diff --git a/source/images/références/références.yaml b/publicodes/source/components/rule/références/références.yaml similarity index 100% rename from source/images/références/références.yaml rename to publicodes/source/components/rule/références/références.yaml diff --git a/source/images/références/senat.png b/publicodes/source/components/rule/références/senat.png similarity index 100% rename from source/images/références/senat.png rename to publicodes/source/components/rule/références/senat.png diff --git a/source/images/références/wikipedia.png b/publicodes/source/components/rule/références/wikipedia.png similarity index 100% rename from source/images/références/wikipedia.png rename to publicodes/source/components/rule/références/wikipedia.png diff --git a/source/engine/controls.js b/publicodes/source/controls.js similarity index 90% rename from source/engine/controls.js rename to publicodes/source/controls.js index 6fc153df8..8d6509b09 100644 --- a/source/engine/controls.js +++ b/publicodes/source/controls.js @@ -1,4 +1,4 @@ -import { evaluateNode } from 'Engine/evaluation' +import { evaluateNode } from './evaluation' export let evaluateControls = (cache, situation, parsedRules) => { return Object.values(parsedRules) diff --git a/source/engine/date.ts b/publicodes/source/date.ts similarity index 100% rename from source/engine/date.ts rename to publicodes/source/date.ts diff --git a/source/engine/error.ts b/publicodes/source/error.ts similarity index 97% rename from source/engine/error.ts rename to publicodes/source/error.ts index eff4b1449..7ccdc88a0 100644 --- a/source/engine/error.ts +++ b/publicodes/source/error.ts @@ -1,4 +1,4 @@ -import { coerceArray } from '../utils' +import { coerceArray } from './utils' export class EngineError extends Error {} export function syntaxError( diff --git a/source/engine/evaluateRule.ts b/publicodes/source/evaluateRule.ts similarity index 96% rename from source/engine/evaluateRule.ts rename to publicodes/source/evaluateRule.ts index 27d7fc662..27f09c253 100644 --- a/source/engine/evaluateRule.ts +++ b/publicodes/source/evaluateRule.ts @@ -1,8 +1,8 @@ -import { bonus, evaluateNode, mergeMissing } from 'Engine/evaluation' -import { ParsedRule } from 'Engine/types' import { map, mergeAll, pick, pipe } from 'ramda' import { typeWarning } from './error' +import { bonus, evaluateNode, mergeMissing } from './evaluation' import { convertNodeToUnit } from './nodeUnits' +import { ParsedRule } from './types' export const evaluateApplicability = ( cache, diff --git a/source/engine/evaluation.tsx b/publicodes/source/evaluation.tsx similarity index 94% rename from source/engine/evaluation.tsx rename to publicodes/source/evaluation.tsx index eb936beb6..261d4da1e 100644 --- a/source/engine/evaluation.tsx +++ b/publicodes/source/evaluation.tsx @@ -11,7 +11,6 @@ import { import React from 'react' import { typeWarning } from './error' import { convertNodeToUnit, simplifyNodeUnit } from './nodeUnits' -import { EvaluatedNode } from 'Engine/types' import { concatTemporals, liftTemporalNode, @@ -21,7 +20,7 @@ import { temporalAverage, zipTemporals } from './temporal' -import { ParsedRule, ParsedRules } from './types' +import { EvaluatedNode, ParsedRule, ParsedRules } from './types' export const makeJsx = (node: EvaluatedNode): JSX.Element => { const Component = node.jsx @@ -209,12 +208,15 @@ export const evaluateObject = (objectShape, effect) => ( } } -type DefaultValues = { [name in Names]: any } | {} +type DefaultValues = Partial< + Record +> export function collectDefaults( parsedRules: ParsedRules ): DefaultValues { - return (Object.values(parsedRules) as Array>).reduce( - (acc, parsedRule) => { + const values: Array> = Object.values(parsedRules) + return values.reduce( + (acc: DefaultValues, parsedRule: ParsedRule) => { if (parsedRule?.['par défaut'] == null) { return acc } diff --git a/source/engine/format.test.js b/publicodes/source/format.test.js similarity index 97% rename from source/engine/format.test.js rename to publicodes/source/format.test.js index c29e1beed..d5f48b074 100644 --- a/source/engine/format.test.js +++ b/publicodes/source/format.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { parseUnit } from 'Engine/units' +import { parseUnit } from './units' import { formatValue } from './format' describe('format engine values', () => { diff --git a/source/engine/format.ts b/publicodes/source/format.ts similarity index 87% rename from source/engine/format.ts rename to publicodes/source/format.ts index 5067acb04..87773e971 100644 --- a/source/engine/format.ts +++ b/publicodes/source/format.ts @@ -1,7 +1,7 @@ -import { serializeUnit } from 'Engine/units' +import { serializeUnit } from './units' import { memoizeWith } from 'ramda' -import { Evaluation } from './types' -import { Unit } from './units' +import { Evaluation, Unit } from './types' +import { capitalise0 } from './utils' const NumberFormat = memoizeWith( (...args) => JSON.stringify(args), @@ -36,14 +36,6 @@ export const numberFormatter = ({ }).format(value) } -export const currencyFormat = (language: string | undefined) => ({ - isCurrencyPrefixed: !!/^€/.exec( - numberFormatter({ language, style: 'currency' })(12) - ), - thousandSeparator: numberFormatter({ language })(1000).charAt(1), - decimalSeparator: numberFormatter({ language })(0.1).charAt(1) -}) - export const formatCurrency = (value: number | undefined, language: string) => { return value == null ? '' @@ -133,7 +125,7 @@ export function formatValue({ return '-' } return typeof nodeValue === 'string' - ? nodeValue + ? capitalise0(nodeValue) : typeof nodeValue === 'object' ? (nodeValue as any).nom : typeof nodeValue === 'boolean' diff --git a/source/engine/getSituationValue.js b/publicodes/source/getSituationValue.js similarity index 100% rename from source/engine/getSituationValue.js rename to publicodes/source/getSituationValue.js diff --git a/source/engine/grammar.ne b/publicodes/source/grammar.ne similarity index 100% rename from source/engine/grammar.ne rename to publicodes/source/grammar.ne diff --git a/source/engine/grammarFunctions.js b/publicodes/source/grammarFunctions.js similarity index 95% rename from source/engine/grammarFunctions.js rename to publicodes/source/grammarFunctions.js index 442b6242d..e4a66afa8 100644 --- a/source/engine/grammarFunctions.js +++ b/publicodes/source/grammarFunctions.js @@ -1,7 +1,7 @@ /* Those are postprocessor functions for the Nearley grammar.ne. The advantage of putting them here is to get prettier's JS formatting, since Nealrey doesn't support it https://github.com/kach/nearley/issues/310 */ -import { normalizeDateString } from 'Engine/date' -import { parseUnit } from 'Engine/units' +import { normalizeDateString } from './date' +import { parseUnit } from './units' import { parsePeriod } from './temporal' export let binaryOperation = operationType => ([A, , operator, , B]) => ({ diff --git a/source/i18n.ts b/publicodes/source/i18n.ts similarity index 89% rename from source/i18n.ts rename to publicodes/source/i18n.ts index 0345e8e1a..285523801 100644 --- a/source/i18n.ts +++ b/publicodes/source/i18n.ts @@ -1,11 +1,10 @@ import i18next from 'i18next' -import { initReactI18next } from 'react-i18next' import unitsTranslations from './locales/units.yaml' - -export type AvailableLangs = 'fr' | 'en' +import { initReactI18next } from 'react-i18next' i18next .use(initReactI18next) + .init({ resources: { fr: { units: unitsTranslations.fr }, diff --git a/source/engine/index.ts b/publicodes/source/index.ts similarity index 80% rename from source/engine/index.ts rename to publicodes/source/index.ts index b94721a10..2c5d7fb2c 100644 --- a/source/engine/index.ts +++ b/publicodes/source/index.ts @@ -1,13 +1,12 @@ -import { evaluateControls } from 'Engine/controls' -import { convertNodeToUnit, simplifyNodeUnit } from 'Engine/nodeUnits' -import { parse } from 'Engine/parse' -import { EvaluatedNode, EvaluatedRule, ParsedRules, Rules } from 'Engine/types' -import { parseUnit } from 'Engine/units' import { mapObjIndexed } from 'ramda' -import { Simulation } from 'Reducers/rootReducer' +import { evaluateControls } from './controls' import { evaluationError, warning } from './error' import { collectDefaults, evaluateNode } from './evaluation' +import { convertNodeToUnit, simplifyNodeUnit } from './nodeUnits' +import { parse } from './parse' import parseRules from './parseRules' +import { EvaluatedNode, EvaluatedRule, ParsedRules, Rules } from './types' +import { parseUnit } from './units' const emptyCache = () => ({ _meta: { contextRule: [] } @@ -22,20 +21,31 @@ type Cache = { } } } +type Situation = Partial< + Record +> + +type EvaluatedSituation = Partial< + Record> +> export type EvaluationOptions = Partial<{ unit: string useDefaultValues: boolean }> +export * from './components' +export { formatValue } from './format' export { default as translateRules } from './translateRules' +export * from './types' export { parseRules } + export default class Engine { parsedRules: ParsedRules - defaultValues: Simulation['situation'] - situation: Simulation['situation'] = {} - private cache: Cache - private cacheWithoutDefault: Cache + defaultValues: Situation + situation: Situation = {} + cache: Cache + cacheWithoutDefault: Cache constructor(rules: string | Rules | ParsedRules) { this.cache = emptyCache() @@ -51,7 +61,7 @@ export default class Engine { ? this.evaluateExpression(value, `[valeur par défaut] ${name}`, false) : value, collectDefaults(this.parsedRules) - ) + ) as EvaluatedSituation } private resetCache() { @@ -70,7 +80,7 @@ export default class Engine { expression: string, context: string, useDefaultValues = true - ): EvaluatedRule { + ): EvaluatedNode { const result = simplifyNodeUnit( evaluateNode( useDefaultValues ? this.cache : this.cacheWithoutDefault, @@ -103,7 +113,7 @@ export default class Engine { ? this.evaluateExpression(value, `[situation] ${name}`, true) : value, situation - ) + ) as EvaluatedSituation return this } @@ -111,11 +121,8 @@ export default class Engine { evaluate( expression: string, options?: EvaluationOptions - ): EvaluatedNode - evaluate( - expression: string, - options?: EvaluationOptions - ): EvaluatedNode { + ): EvaluatedNode | EvaluatedRule + evaluate(expression: string, options?: EvaluationOptions) { let result = this.evaluateExpression( expression, `[evaluation] ${expression}`, @@ -124,12 +131,12 @@ export default class Engine { if (result.category === 'reference' && result.explanation) { result = { nodeValue: result.nodeValue, - unit: result.unit, + ...('unit' in result && { unit: result.unit }), ...('temporalValue' in result && { temporalValue: result.temporalValue }), ...result.explanation - } + } as EvaluatedRule } if (options?.unit) { try { diff --git a/source/locales/units.yaml b/publicodes/source/locales/units.yaml similarity index 100% rename from source/locales/units.yaml rename to publicodes/source/locales/units.yaml diff --git a/publicodes/source/locales/writtenNumbers.yaml b/publicodes/source/locales/writtenNumbers.yaml new file mode 100644 index 000000000..d0ef44e33 --- /dev/null +++ b/publicodes/source/locales/writtenNumbers.yaml @@ -0,0 +1,25 @@ +en: + - zero + - one + - two + - three + - four + - five + - six + - seven + - eight + - nine + - ten + +fr: + - zéro + - un + - deux + - trois + - quatre + - cinq + - six + - sept + - huit + - neuf + - dix diff --git a/source/engine/mecanisms.tsx b/publicodes/source/mecanisms.tsx similarity index 95% rename from source/engine/mecanisms.tsx rename to publicodes/source/mecanisms.tsx index ce507a971..8a28bdb60 100644 --- a/source/engine/mecanisms.tsx +++ b/publicodes/source/mecanisms.tsx @@ -1,12 +1,3 @@ -import { decompose } from 'Engine/mecanisms/utils' -import variations from 'Engine/mecanisms/variations' -import { convertNodeToUnit } from 'Engine/nodeUnits' -import { - areUnitConvertible, - convertUnit, - inferUnit, - serializeUnit -} from 'Engine/units' import { any, equals, @@ -20,6 +11,12 @@ import { reduce } from 'ramda' import React from 'react' +import Allègement from './components/mecanisms/Allègement' +import { Node } from './components/mecanisms/common' +import InversionNumérique from './components/mecanisms/InversionNumérique' +import Product from './components/mecanisms/Product' +import Recalcul from './components/mecanisms/Recalcul' +import Somme from './components/mecanisms/Somme' import { typeWarning } from './error' import { collectNodeMissing, @@ -31,15 +28,19 @@ import { mergeAllMissing, parseObject } from './evaluation' -import Allègement from './mecanismViews/Allègement' -import { Node, SimpleRuleLink } from './mecanismViews/common' -import InversionNumérique from './mecanismViews/InversionNumérique' -import Product from './mecanismViews/Product' -import Recalcul from './mecanismViews/Recalcul' -import Somme from './mecanismViews/Somme' -import uniroot from './uniroot' -import { parseUnit } from './units' +import { decompose } from './mecanisms/utils' +import variations from './mecanisms/variations' +import { convertNodeToUnit } from './nodeUnits' import { EvaluatedRule } from './types' +import uniroot from './uniroot' +import { + areUnitConvertible, + convertUnit, + inferUnit, + parseUnit, + serializeUnit +} from './units' +import { RuleLinkWithContext } from './components/RuleLink' export const mecanismOneOf = (recurse, k, v) => { if (!is(Array, v)) throw new Error('should be array') @@ -609,7 +610,8 @@ export const mecanismSynchronisation = (recurse, k, v) => { jsx: function Synchronisation({ explanation }) { return (

        - Obtenu à partir de la saisie + Obtenu à partir de la saisie{' '} +

        ) }, diff --git a/source/engine/mecanisms.yaml b/publicodes/source/mecanisms.yaml similarity index 100% rename from source/engine/mecanisms.yaml rename to publicodes/source/mecanisms.yaml diff --git a/source/engine/mecanisms/arrondi.tsx b/publicodes/source/mecanisms/arrondi.tsx similarity index 89% rename from source/engine/mecanisms/arrondi.tsx rename to publicodes/source/mecanisms/arrondi.tsx index a798b7881..26da808de 100644 --- a/source/engine/mecanisms/arrondi.tsx +++ b/publicodes/source/mecanisms/arrondi.tsx @@ -3,12 +3,12 @@ import { evaluateNode, makeJsx, mergeAllMissing -} from 'Engine/evaluation' -import { Node } from 'Engine/mecanismViews/common' -import { simplifyNodeUnit } from 'Engine/nodeUnits' -import { mapTemporal, pureTemporal, temporalAverage } from 'Engine/temporal' -import { serializeUnit } from 'Engine/units' -import { EvaluatedRule, Evaluation, EvaluatedNode } from 'Engine/types' +} from '../evaluation' +import { Node } from '../components/mecanisms/common' +import { simplifyNodeUnit } from '../nodeUnits' +import { mapTemporal, pureTemporal, temporalAverage } from '../temporal' +import { serializeUnit } from '../units' +import { EvaluatedRule, Evaluation, EvaluatedNode } from '../types' import { has } from 'ramda' import React from 'react' import { Trans } from 'react-i18next' diff --git a/source/engine/mecanisms/barème.ts b/publicodes/source/mecanisms/barème.ts similarity index 88% rename from source/engine/mecanisms/barème.ts rename to publicodes/source/mecanisms/barème.ts index d76ef24d1..26b5e1b4f 100644 --- a/source/engine/mecanisms/barème.ts +++ b/publicodes/source/mecanisms/barème.ts @@ -1,20 +1,19 @@ -import { evaluationError } from 'Engine/error' -import { defaultNode, evaluateNode, mergeAllMissing } from 'Engine/evaluation' -import { decompose } from 'Engine/mecanisms/utils' -import variations from 'Engine/mecanisms/variations' -import Barème from 'Engine/mecanismViews/Barème' +import Barème from '../components/mecanisms/Barème' +import { evaluationError } from '../error' +import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation' import { liftTemporal2, liftTemporalNode, mapTemporal, temporalAverage -} from 'Engine/temporal' -import { convertUnit } from '../units' -import { parseUnit } from './../units' +} from '../temporal' +import { convertUnit, parseUnit } from '../units' import { evaluatePlafondUntilActiveTranche, parseTranches } from './trancheUtils' +import { decompose } from './utils' +import variations from './variations' export default function parse(parse, k, v) { // Barème en taux marginaux. diff --git a/source/engine/mecanisms/durée.tsx b/publicodes/source/mecanisms/durée.tsx similarity index 90% rename from source/engine/mecanisms/durée.tsx rename to publicodes/source/mecanisms/durée.tsx index 1cf434b79..625fa4dd1 100644 --- a/source/engine/mecanisms/durée.tsx +++ b/publicodes/source/mecanisms/durée.tsx @@ -1,13 +1,13 @@ -import { convertToDate, convertToString } from 'Engine/date' +import { convertToDate, convertToString } from '../date' import { defaultNode, evaluateNode, makeJsx, mergeMissing, parseObject -} from 'Engine/evaluation' -import { Node } from 'Engine/mecanismViews/common' -import { parseUnit } from 'Engine/units' +} from '../evaluation' +import { Node } from '../components/mecanisms/common' +import { parseUnit } from '../units' import React from 'react' function MecanismDurée({ nodeValue, explanation, unit }) { diff --git a/source/engine/mecanisms/encadrement.tsx b/publicodes/source/mecanisms/encadrement.tsx similarity index 54% rename from source/engine/mecanisms/encadrement.tsx rename to publicodes/source/mecanisms/encadrement.tsx index 0eac500a4..4f139eed0 100644 --- a/source/engine/mecanisms/encadrement.tsx +++ b/publicodes/source/mecanisms/encadrement.tsx @@ -1,55 +1,50 @@ -import { typeWarning } from 'Engine/error' +import React from 'react' +import { Node } from '../components/mecanisms/common' +import { typeWarning } from '../error' import { defaultNode, evaluateObject, makeJsx, parseObject -} from 'Engine/evaluation' -import { Node } from 'Engine/mecanismViews/common' -import { convertNodeToUnit } from 'Engine/nodeUnits' -import React from 'react' +} from '../evaluation' +import { convertNodeToUnit } from '../nodeUnits' function MecanismEncadrement({ nodeValue, explanation, unit }) { return ( - - <> - {makeJsx(explanation.valeur)} -
        - {!explanation.plancher.isDefault && ( - - Minimum : - {makeJsx(explanation.plancher)} - - )} - {!explanation.plafond.isDefault && ( - <> -
        - - Plafonné à : - {makeJsx(explanation.plafond)} - - - )} -
        - -
        +
        + {makeJsx(explanation.valeur)} + {!explanation.plancher.isDefault && ( + <> +
        + + + Minimum : + {makeJsx(explanation.plancher)} + + + )} + {!explanation.plafond.isDefault && ( + <> +
        + + Plafonné à : + {makeJsx(explanation.plafond)} + + + )} +
        ) } diff --git a/source/engine/mecanisms/grille.ts b/publicodes/source/mecanisms/grille.ts similarity index 90% rename from source/engine/mecanisms/grille.ts rename to publicodes/source/mecanisms/grille.ts index 94fe7ba4b..cedc5c939 100644 --- a/source/engine/mecanisms/grille.ts +++ b/publicodes/source/mecanisms/grille.ts @@ -1,15 +1,15 @@ -import { defaultNode, evaluateNode, mergeAllMissing } from 'Engine/evaluation' -import { decompose } from 'Engine/mecanisms/utils' -import variations from 'Engine/mecanisms/variations' -import grille from 'Engine/mecanismViews/Grille' +import { lensPath, over } from 'ramda' +import grille from '../components/mecanisms/Grille' +import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation' +import { decompose } from '../mecanisms/utils' +import variations from '../mecanisms/variations' import { liftTemporal2, liftTemporalNode, mapTemporal, temporalAverage -} from 'Engine/temporal' -import { parseUnit } from 'Engine/units' -import { lensPath, over } from 'ramda' +} from '../temporal' +import { parseUnit } from '../units' import { evaluatePlafondUntilActiveTranche, parseTranches diff --git a/source/engine/mecanisms/operation.js b/publicodes/source/mecanisms/operation.js similarity index 87% rename from source/engine/mecanisms/operation.js rename to publicodes/source/mecanisms/operation.js index cfea025e7..582141527 100644 --- a/source/engine/mecanisms/operation.js +++ b/publicodes/source/mecanisms/operation.js @@ -1,10 +1,10 @@ -import { convertToDate } from 'Engine/date' -import { typeWarning } from 'Engine/error' -import { evaluateNode, makeJsx, mergeMissing } from 'Engine/evaluation' -import { Node } from 'Engine/mecanismViews/common' -import { convertNodeToUnit } from 'Engine/nodeUnits' -import { liftTemporal2, pureTemporal, temporalAverage } from 'Engine/temporal' -import { inferUnit, serializeUnit } from 'Engine/units' +import { convertToDate } from '../date' +import { typeWarning } from '../error' +import { evaluateNode, makeJsx, mergeMissing } from '../evaluation' +import { Node } from '../components/mecanisms/common' +import { convertNodeToUnit } from '../nodeUnits' +import { liftTemporal2, pureTemporal, temporalAverage } from '../temporal' +import { inferUnit, serializeUnit } from '../units' import { curry, map } from 'ramda' import React from 'react' diff --git a/source/engine/mecanisms/régularisation.ts b/publicodes/source/mecanisms/régularisation.ts similarity index 73% rename from source/engine/mecanisms/régularisation.ts rename to publicodes/source/mecanisms/régularisation.ts index 9b2dd6b94..a6db5006f 100644 --- a/source/engine/mecanisms/régularisation.ts +++ b/publicodes/source/mecanisms/régularisation.ts @@ -1,7 +1,7 @@ -import { convertToString, getYear } from 'Engine/date' -import { evaluationError } from 'Engine/error' -import { evaluateNode } from 'Engine/evaluation' -import { Evaluation } from 'Engine/types' +import { map } from 'ramda' +import { convertToString, getYear } from '../date' +import { evaluationError } from '../error' +import { evaluateNode } from '../evaluation' import { createTemporalEvaluation, groupByYear, @@ -10,11 +10,9 @@ import { Temporal, temporalAverage, temporalCumul -} from 'Engine/temporal' -import { Unit } from 'Engine/units' -import { coerceArray } from '../../utils' -import { DottedName } from './../../rules/index' -import { map } from 'ramda' +} from '../temporal' +import { Evaluation, Unit } from '../types' +import { coerceArray } from '../utils' function stripTemporalTransform(node) { if (!node?.explanation?.period) { @@ -22,7 +20,7 @@ function stripTemporalTransform(node) { } return stripTemporalTransform(node.explanation.value) } -export default function parse(parse, k, v) { +export default function parse(parse, k, v) { const rule = parse(v.règle) if (!v['valeurs cumulées']) { throw new Error( @@ -45,7 +43,7 @@ export default function parse(parse, k, v) { ) } return { value, dottedName: reference.dottedName } - }) as Array<{ dottedName: DottedName; value: object }> + }) as Array<{ dottedName: Name; value: object }> return { evaluate, @@ -86,12 +84,7 @@ function getMonthlyCumulatedValuesOverYear( return cumulatedPeriods } -function evaluate( - cache, - situation, - parsedRules, - node: ReturnType -) { +function evaluate(cache, situation, parsedRules, node) { const evaluate = evaluateNode.bind(null, cache, situation, parsedRules) function recalculWith(newSituation, node) { @@ -109,25 +102,29 @@ function evaluate( } const currentYear = getYear(temporalEvaluation[0].start as string) - const cumulatedVariables = node.explanation.variables.reduce< - Record>> - >((acc, { dottedName, value }) => { - const evaluation = evaluate(value) - if (!evaluation.unit.denominators.some(unit => unit === 'mois')) { - evaluationError( - cache._meta.contextRule, - `Dans le mécanisme régularisation, la valeur cumulée '${dottedName}' n'est pas une variable numérique définie sur le mois` - ) - } - return { - ...acc, - [dottedName]: getMonthlyCumulatedValuesOverYear( - currentYear, - evaluation.temporalValue ?? pureTemporal(evaluation.nodeValue), - evaluation.unit - ) - } - }, {}) + const cumulatedVariables = (node.explanation.variables as Array<{ + dottedName: string + value: object + }>).reduce>>>( + (acc, { dottedName, value }) => { + const evaluation = evaluate(value) + if (!evaluation.unit.denominators.some(unit => unit === 'mois')) { + evaluationError( + cache._meta.contextRule, + `Dans le mécanisme régularisation, la valeur cumulée '${dottedName}' n'est pas une variable numérique définie sur le mois` + ) + } + return { + ...acc, + [dottedName]: getMonthlyCumulatedValuesOverYear( + currentYear, + evaluation.temporalValue ?? pureTemporal(evaluation.nodeValue), + evaluation.unit + ) + } + }, + {} + ) const cumulatedMonthlyEvaluations = [...Array(12).keys()].map(i => ({ start: convertToString(new Date(currentYear, i, 1)), diff --git a/source/engine/mecanisms/tauxProgressif.ts b/publicodes/source/mecanisms/tauxProgressif.ts similarity index 90% rename from source/engine/mecanisms/tauxProgressif.ts rename to publicodes/source/mecanisms/tauxProgressif.ts index e23ce0906..ace9738d2 100644 --- a/source/engine/mecanisms/tauxProgressif.ts +++ b/publicodes/source/mecanisms/tauxProgressif.ts @@ -1,9 +1,9 @@ -import { defaultNode, evaluateNode, mergeAllMissing } from 'Engine/evaluation' -import { decompose } from 'Engine/mecanisms/utils' -import variations from 'Engine/mecanisms/variations' -import tauxProgressif from 'Engine/mecanismViews/TauxProgressif' -import { convertNodeToUnit } from 'Engine/nodeUnits' -import { parseUnit } from 'Engine/units' +import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation' +import { decompose } from './utils' +import variations from './variations' +import tauxProgressif from '../components/mecanisms/TauxProgressif' +import { convertNodeToUnit } from '../nodeUnits' +import { parseUnit } from '../units' import { evaluatePlafondUntilActiveTranche, parseTranches diff --git a/source/engine/mecanisms/trancheUtils.ts b/publicodes/source/mecanisms/trancheUtils.ts similarity index 97% rename from source/engine/mecanisms/trancheUtils.ts rename to publicodes/source/mecanisms/trancheUtils.ts index d7e8779b8..d9f8ea36d 100644 --- a/source/engine/mecanisms/trancheUtils.ts +++ b/publicodes/source/mecanisms/trancheUtils.ts @@ -1,7 +1,7 @@ -import { mergeAllMissing } from 'Engine/evaluation' -import { Evaluation } from 'Engine/types' import { evolve } from 'ramda' import { evaluationError, typeWarning } from '../error' +import { mergeAllMissing } from '../evaluation' +import { Evaluation } from '../types' import { convertUnit, inferUnit } from '../units' export const parseTranches = (parse, tranches) => { diff --git a/source/engine/mecanisms/utils.js b/publicodes/source/mecanisms/utils.js similarity index 86% rename from source/engine/mecanisms/utils.js rename to publicodes/source/mecanisms/utils.js index 212733abf..e7f695e58 100644 --- a/source/engine/mecanisms/utils.js +++ b/publicodes/source/mecanisms/utils.js @@ -1,7 +1,7 @@ -import Composantes from 'Engine/mecanismViews/Composantes' import { add, dissoc, objOf } from 'ramda' -import { evaluateArrayWithFilter } from 'Engine/evaluation' -import { inferUnit } from 'Engine/units' +import { evaluateArrayWithFilter } from '../evaluation' +import { inferUnit } from '../units' +import Composantes from '../components/mecanisms/Composantes' export let decompose = (recurse, k, v) => { let subProps = dissoc('composantes')(v), diff --git a/source/engine/mecanisms/variableTemporelle.ts b/publicodes/source/mecanisms/variableTemporelle.ts similarity index 92% rename from source/engine/mecanisms/variableTemporelle.ts rename to publicodes/source/mecanisms/variableTemporelle.ts index 54aaaebd5..b1a315af0 100644 --- a/source/engine/mecanisms/variableTemporelle.ts +++ b/publicodes/source/mecanisms/variableTemporelle.ts @@ -1,10 +1,10 @@ -import { evaluateNode } from 'Engine/evaluation' +import { evaluateNode } from '../evaluation' import { createTemporalEvaluation, narrowTemporalValue, + Temporal, temporalAverage -} from 'Engine/temporal' -import { Temporal } from './../temporal' +} from '../temporal' function evaluate( cache: any, diff --git a/source/engine/mecanisms/variations.ts b/publicodes/source/mecanisms/variations.ts similarity index 92% rename from source/engine/mecanisms/variations.ts rename to publicodes/source/mecanisms/variations.ts index e7e5c13a7..e854fa5b3 100644 --- a/source/engine/mecanisms/variations.ts +++ b/publicodes/source/mecanisms/variations.ts @@ -1,17 +1,16 @@ -import { typeWarning } from 'Engine/error' -import { bonus, defaultNode, evaluateNode } from 'Engine/evaluation' -import Variations from 'Engine/mecanismViews/Variations' -import { convertNodeToUnit } from 'Engine/nodeUnits' +import { or } from 'ramda' +import Variations from '../components/mecanisms/Variations' +import { typeWarning } from '../error' +import { bonus, defaultNode, evaluateNode } from '../evaluation' +import { convertNodeToUnit } from '../nodeUnits' import { liftTemporal2, pureTemporal, sometime, temporalAverage -} from 'Engine/temporal' -import { inferUnit } from 'Engine/units' -import { or } from 'ramda' +} from '../temporal' +import { inferUnit } from '../units' import { mergeAllMissing } from './../evaluation' -import { parseUnit } from './../units' /* @devariate = true => This function will produce variations of a same mecanism (e.g. product) that share some common properties */ export default function parse(recurse, k, v, devariate) { diff --git a/source/engine/nodeUnits.ts b/publicodes/source/nodeUnits.ts similarity index 87% rename from source/engine/nodeUnits.ts rename to publicodes/source/nodeUnits.ts index a705086c0..00a35e344 100644 --- a/source/engine/nodeUnits.ts +++ b/publicodes/source/nodeUnits.ts @@ -1,6 +1,6 @@ import { mapTemporal } from './temporal' -import { convertUnit, simplifyUnit, Unit } from './units' -import { EvaluatedNode } from './types' +import { convertUnit, simplifyUnit } from './units' +import { EvaluatedNode, Unit } from './types' export function simplifyNodeUnit(node) { if (!node.unit) { diff --git a/source/engine/parse.tsx b/publicodes/source/parse.tsx similarity index 91% rename from source/engine/parse.tsx rename to publicodes/source/parse.tsx index d976e8403..ea00ddee2 100644 --- a/source/engine/parse.tsx +++ b/publicodes/source/parse.tsx @@ -2,16 +2,16 @@ // In a specific file // TODO import them automatically // TODO convert the legacy functions to new files -import mecanismRound, { unchainRoundMecanism } from 'Engine/mecanisms/arrondi' -import barème from 'Engine/mecanisms/barème' -import durée from 'Engine/mecanisms/durée' -import encadrement from 'Engine/mecanisms/encadrement' -import grille from 'Engine/mecanisms/grille' -import operation from 'Engine/mecanisms/operation' -import régularisation from 'Engine/mecanisms/régularisation' -import tauxProgressif from 'Engine/mecanisms/tauxProgressif' -import variableTemporelle from 'Engine/mecanisms/variableTemporelle' -import variations from 'Engine/mecanisms/variations' +import mecanismRound, { unchainRoundMecanism } from './mecanisms/arrondi' +import barème from './mecanisms/barème' +import durée from './mecanisms/durée' +import encadrement from './mecanisms/encadrement' +import grille from './mecanisms/grille' +import operation from './mecanisms/operation' +import régularisation from './mecanisms/régularisation' +import tauxProgressif from './mecanisms/tauxProgressif' +import variableTemporelle from './mecanisms/variableTemporelle' +import variations from './mecanisms/variations' import { Grammar, Parser } from 'nearley' import { add, diff --git a/source/engine/parseReference.js b/publicodes/source/parseReference.js similarity index 98% rename from source/engine/parseReference.js rename to publicodes/source/parseReference.js index 4e1523643..f017a77b8 100644 --- a/source/engine/parseReference.js +++ b/publicodes/source/parseReference.js @@ -1,14 +1,14 @@ -// Reference to a variable -import parseRule from 'Engine/parseRule' import React from 'react' +import { Leaf } from './components/mecanisms/common' import { typeWarning } from './error' import { evaluateApplicability } from './evaluateRule' import { evaluateNode, mergeMissing } from './evaluation' import { getSituationValue } from './getSituationValue' -import { Leaf } from './mecanismViews/common' import { convertNodeToUnit } from './nodeUnits' +import parseRule from './parseRule' import { disambiguateRuleReference } from './ruleUtils' import { areUnitConvertible, serializeUnit } from './units' + const getApplicableReplacements = ( filter, contextRuleName, diff --git a/source/engine/parseRule.tsx b/publicodes/source/parseRule.tsx similarity index 97% rename from source/engine/parseRule.tsx rename to publicodes/source/parseRule.tsx index e60f8f4bd..f2996254a 100644 --- a/source/engine/parseRule.tsx +++ b/publicodes/source/parseRule.tsx @@ -1,12 +1,11 @@ -import RuleLink from 'Components/RuleLink' import { evolve, map } from 'ramda' import React from 'react' import { Trans } from 'react-i18next' -import { capitalise0, coerceArray } from '../utils' +import { Node } from './components/mecanisms/common' +import { RuleLinkWithContext } from './components/RuleLink' import { warning } from './error' import evaluate from './evaluateRule' import { evaluateNode, makeJsx, mergeAllMissing } from './evaluation' -import { Node } from './mecanismViews/common' import { parse } from './parse' import { disambiguateRuleReference, @@ -15,6 +14,7 @@ import { } from './ruleUtils' import { ParsedRule, Rule, Rules } from './types' import { parseUnit, simplifyUnit } from './units' +import { capitalise0, coerceArray } from './utils' export default function( rules: Rules, @@ -215,7 +215,7 @@ export default function( {isDisabledBy.map((rule, i) => ( {i > 0 && ', '} - + ))}

        diff --git a/source/engine/parseRules.ts b/publicodes/source/parseRules.ts similarity index 98% rename from source/engine/parseRules.ts rename to publicodes/source/parseRules.ts index 77028b752..dc9ae9e47 100644 --- a/source/engine/parseRules.ts +++ b/publicodes/source/parseRules.ts @@ -1,4 +1,4 @@ -import parseRule from 'Engine/parseRule' +import parseRule from './parseRule' import yaml from 'yaml' import { lensPath, set } from 'ramda' import { compilationError } from './error' diff --git a/source/engine/ruleUtils.ts b/publicodes/source/ruleUtils.ts similarity index 65% rename from source/engine/ruleUtils.ts rename to publicodes/source/ruleUtils.ts index b99e0a9b3..3047aacbd 100644 --- a/source/engine/ruleUtils.ts +++ b/publicodes/source/ruleUtils.ts @@ -1,6 +1,5 @@ -import { dropLast, last, pipe, propEq, range, take } from 'ramda' -import { coerceArray } from '../utils' -import { EvaluatedRule, Rule, Rules } from './types' +import { dropLast, last, pipe, range, take } from 'ramda' +import { Rule, Rules } from './types' export const splitName = (str: string) => str.split(' . ') export const joinName = strs => strs.join(' . ') @@ -11,19 +10,15 @@ export const parentName = pipe( ) export const nameLeaf = pipe(splitName, last) export const encodeRuleName = name => - encodeURI( - name - .replace(/\s\.\s/g, '/') - .replace(/-/g, '\u2011') // replace with a insecable tiret to differenciate from space - .replace(/\s/g, '-') - ) + name + .replace(/\s\.\s/g, '/') + .replace(/-/g, '\u2011') // replace with a insecable tiret to differenciate from space + .replace(/\s/g, '-') export const decodeRuleName = name => - decodeURI( - name - .replace(/\//g, ' . ') - .replace(/-/g, ' ') - .replace(/\u2011/g, '-') - ) + name + .replace(/\//g, ' . ') + .replace(/-/g, ' ') + .replace(/\u2011/g, '-') export function ruleParents( dottedName: Names ): Array { @@ -79,24 +74,3 @@ export function findParentDependencies( ) .map(([name, _]) => name) } - -export const getRuleFromAnalysis = analysis => ( - dottedName: Names -): EvaluatedRule => { - if (!analysis) { - throw new Error("[getRuleFromAnalysis] The analysis can't be nil !") - } - - const rule = coerceArray(analysis) // In some simulations, there are multiple "branches" : the analysis is run with e.g. 3 different input situations - .map( - analysis => - analysis.cache[dottedName]?.explanation || // the cache stores a reference to a variable, the variable is contained in the 'explanation' attribute - analysis.targets.find(propEq('dottedName', dottedName)) - ) - .filter(Boolean)[0] - if (process.env.NODE_ENV !== 'production' && !rule) { - console.warn(`[getRuleFromAnalysis] Unable to find the rule ${dottedName}`) - } - - return rule -} diff --git a/source/engine/temporal.ts b/publicodes/source/temporal.ts similarity index 98% rename from source/engine/temporal.ts rename to publicodes/source/temporal.ts index ea5ab53b3..5a8b0a385 100644 --- a/source/engine/temporal.ts +++ b/publicodes/source/temporal.ts @@ -5,9 +5,8 @@ import { getDifferenceInYears, getRelativeDate, getYear -} from 'Engine/date' -import { EvaluatedNode, Evaluation, Types } from './types' -import { Unit } from './units' +} from './date' +import { EvaluatedNode, Unit, Evaluation, Types } from './types' export type Period = { start: T | null diff --git a/source/engine/translateRules.ts b/publicodes/source/translateRules.ts similarity index 100% rename from source/engine/translateRules.ts rename to publicodes/source/translateRules.ts diff --git a/publicodes/source/types/import-modules.ts b/publicodes/source/types/import-modules.ts new file mode 100644 index 000000000..8d4a991f5 --- /dev/null +++ b/publicodes/source/types/import-modules.ts @@ -0,0 +1,14 @@ +declare module '*.md' { + const content: string + export default content +} +declare module '*.ne' { + const content: any + export default content +} + +// TODO: We could have better types for yaml imports (it works automatically for JSON modules) +declare module '*.yaml' { + const content: any + export default content +} diff --git a/source/engine/types.ts b/publicodes/source/types/index.ts similarity index 94% rename from source/engine/types.ts rename to publicodes/source/types/index.ts index df38097c9..053a72732 100644 --- a/source/engine/types.ts +++ b/publicodes/source/types/index.ts @@ -1,5 +1,4 @@ -import { Temporal } from './temporal' -import { Unit } from './units' +import { Temporal } from '../temporal' type Contrôle = { si: string @@ -11,6 +10,13 @@ type Contrôle = { } } +type BaseUnit = string + +export type Unit = { + numerators: Array + denominators: Array +} + export type Rule = { formule?: string question?: string @@ -45,7 +51,6 @@ export type ParsedRule = Rule & { explanation?: any isDisabledBy?: Array replacedBy?: Array - category?: string rulePropType?: string jsx?: Function cotisation?: Partial<{ @@ -77,6 +82,7 @@ export type EvaluatedNode< explanation?: Record isDefault?: boolean jsx: React.FunctionComponent + category?: string missingVariables: Partial> } & (T extends number ? { diff --git a/source/engine/uniroot.ts b/publicodes/source/uniroot.ts similarity index 100% rename from source/engine/uniroot.ts rename to publicodes/source/uniroot.ts diff --git a/source/engine/units.ts b/publicodes/source/units.ts similarity index 97% rename from source/engine/units.ts rename to publicodes/source/units.ts index 228b94c02..9065df112 100644 --- a/source/engine/units.ts +++ b/publicodes/source/units.ts @@ -11,15 +11,8 @@ import { unnest, without } from 'ramda' -import i18n from '../i18n' -import { Evaluation } from './types' - -type BaseUnit = string - -export type Unit = { - numerators: Array - denominators: Array -} +import i18n from './i18n' +import { Evaluation, Unit } from './types' //TODO this function does not handle complex units like passenger-kilometer/flight export const parseUnit = (string: string, lng = 'fr'): Unit => { diff --git a/publicodes/source/utils.ts b/publicodes/source/utils.ts new file mode 100644 index 000000000..b6c68b1a2 --- /dev/null +++ b/publicodes/source/utils.ts @@ -0,0 +1,8 @@ +export function coerceArray(x: A | Array): Array { + return Array.isArray(x) ? x : [x] +} +export function capitalise0(name: undefined): undefined +export function capitalise0(name: string): string +export function capitalise0(name?: string) { + return name && name[0].toUpperCase() + name.slice(1) +} diff --git a/publicodes/test/.eslintrc.yaml b/publicodes/test/.eslintrc.yaml new file mode 100644 index 000000000..9808c3b2b --- /dev/null +++ b/publicodes/test/.eslintrc.yaml @@ -0,0 +1,2 @@ +env: + mocha: true diff --git a/test/contrôles.test.js b/publicodes/test/contrôles.test.js similarity index 97% rename from test/contrôles.test.js rename to publicodes/test/contrôles.test.js index 48dcdd6a2..c65ac7b53 100644 --- a/test/contrôles.test.js +++ b/publicodes/test/contrôles.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import Engine, { parseRules } from 'Engine' +import Engine, { parseRules } from 'publicodes' describe('controls', function() { let rawRules = { diff --git a/test/date.test.js b/publicodes/test/date.test.js similarity index 90% rename from test/date.test.js rename to publicodes/test/date.test.js index b8c6779ee..a9dc651b4 100644 --- a/test/date.test.js +++ b/publicodes/test/date.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { getDifferenceInMonths } from '../source/engine/date' +import { getDifferenceInMonths } from '../source/date' describe('Date : getDifferenceInMonths', () => { it('should compute the difference for one full month', () => { diff --git a/test/inversion.test.js b/publicodes/test/inversion.test.js similarity index 99% rename from test/inversion.test.js rename to publicodes/test/inversion.test.js index bb6cb3438..d46ef1e3f 100644 --- a/test/inversion.test.js +++ b/publicodes/test/inversion.test.js @@ -1,6 +1,6 @@ import { expect } from 'chai' import dedent from 'dedent-js' -import Engine from 'Engine' +import Engine from 'publicodes' describe('inversions', () => { it('should handle non inverted example', () => { diff --git a/publicodes/test/library.test.js b/publicodes/test/library.test.js new file mode 100644 index 000000000..e1dff72ff --- /dev/null +++ b/publicodes/test/library.test.js @@ -0,0 +1,75 @@ +import { expect } from 'chai' +import Engine from '../source/index' +import co2 from './rules/co2.yaml' + +describe('library', function() { + it('should let the user define its own rule', function() { + let rules = ` +yo: + formule: 200 +ya: + formule: yo + 1 +yi: + formule: yo + 2 +` + let engine = new Engine(rules) + + expect(engine.evaluate('ya').nodeValue).to.equal(201) + expect(engine.evaluate('yi').nodeValue).to.equal(202) + }) + + it('should let the user define a simplified revenue tax system', function() { + let rules = ` +revenu imposable: + question: Quel est votre revenu imposable ? + unité: € + +revenu abattu: + formule: + allègement: + assiette: revenu imposable + abattement: 10% + +impôt sur le revenu: + formule: + barème: + assiette: revenu abattu + tranches: + - taux: 0% + plafond: 9807 € + - taux: 14% + plafond: 27086 € + - taux: 30% + plafond: 72617 € + - taux: 41% + plafond: 153783 € + - taux: 45% + +impôt sur le revenu à payer: + formule: + allègement: + assiette: impôt sur le revenu + décote: + taux: 75% + plafond: 1177 +` + + let engine = new Engine(rules) + engine.setSituation({ + 'revenu imposable': '48000' + }) + let value = engine.evaluate('impôt sur le revenu à payer') + expect(value.nodeValue).to.equal(7253.26) + }) + + it('should let the user define a rule base on a completely different subject', function() { + let engine = new Engine(co2) + engine.setSituation({ + 'nombre de douches': 30, + 'chauffage . type': "'gaz'", + 'durée de la douche': 10 + }) + let value = engine.evaluate('douche . impact') + expect(value.nodeValue).to.be.within(20, 21) + }) +}) diff --git a/test/load-mecanism-tests.js b/publicodes/test/load-mecanism-tests.js similarity index 100% rename from test/load-mecanism-tests.js rename to publicodes/test/load-mecanism-tests.js diff --git a/test/mecanisms.test.js b/publicodes/test/mecanisms.test.js similarity index 95% rename from test/mecanisms.test.js rename to publicodes/test/mecanisms.test.js index 7001cd85e..7dab3b205 100644 --- a/test/mecanisms.test.js +++ b/publicodes/test/mecanisms.test.js @@ -6,8 +6,8 @@ */ import { expect } from 'chai' -import Engine from 'Engine' -import { parseUnit } from '../source/engine/units' +import Engine from 'publicodes' +import { parseUnit } from '../source/units' import { coerceArray } from '../source/utils' import testSuites from './load-mecanism-tests' testSuites.forEach(([suiteName, suite]) => { diff --git a/test/missingVariables.test.js b/publicodes/test/missingVariables.test.js similarity index 81% rename from test/missingVariables.test.js rename to publicodes/test/missingVariables.test.js index 70f0e356d..b993cfeb5 100644 --- a/test/missingVariables.test.js +++ b/publicodes/test/missingVariables.test.js @@ -1,7 +1,5 @@ import { expect } from 'chai' -import Engine from 'Engine' -import rules from 'Rules' -import { getNextSteps } from '../source/components/utils/useNextQuestion' +import Engine from 'publicodes' describe('Missing variables', function() { it('should identify missing variables', function() { @@ -244,60 +242,4 @@ describe('nextSteps', function() { expect(result).to.eql(['top . sum . evt']) }) - - it('should ask "motif CDD" if "CDD" applies', function() { - const result = Object.keys( - new Engine(rules) - .setSituation({ - 'contrat salarié': 'oui', - 'contrat salarié . CDD': 'oui', - 'contrat salarié . rémunération . brut de base': '2300' - }) - .evaluate('contrat salarié . rémunération . net', { - useDefaultValues: false - }).missingVariables - ) - - expect(result).to.include('contrat salarié . CDD . motif') - }) -}) - -describe('getNextSteps', function() { - it('should give priority to questions that advance most targets', function() { - let missingVariablesByTarget = [ - { - effectif: 34.01, - cadre: 30 - }, - { - cadre: 10.1 - }, - { - effectif: 32.0, - cadre: 10 - } - ] - - let result = getNextSteps(missingVariablesByTarget) - - expect(result[0]).to.equal('cadre') - }) - - it('should give priority to questions by total weight when advancing the same target count', function() { - let missingVariablesByTarget = [ - { - effectif: 24.01, - cadre: 30 - }, - { - effectif: 24.01, - cadre: 10.1 - }, - {} - ] - - let result = getNextSteps(missingVariablesByTarget) - - expect(result[0]).to.equal('effectif') - }) }) diff --git a/test/mécanismes/allègement.yaml b/publicodes/test/mécanismes/allègement.yaml similarity index 100% rename from test/mécanismes/allègement.yaml rename to publicodes/test/mécanismes/allègement.yaml diff --git a/test/mécanismes/applicable.yaml b/publicodes/test/mécanismes/applicable.yaml similarity index 100% rename from test/mécanismes/applicable.yaml rename to publicodes/test/mécanismes/applicable.yaml diff --git a/test/mécanismes/arrondi.yaml b/publicodes/test/mécanismes/arrondi.yaml similarity index 100% rename from test/mécanismes/arrondi.yaml rename to publicodes/test/mécanismes/arrondi.yaml diff --git a/test/mécanismes/barème.yaml b/publicodes/test/mécanismes/barème.yaml similarity index 100% rename from test/mécanismes/barème.yaml rename to publicodes/test/mécanismes/barème.yaml diff --git a/test/mécanismes/composantes.yaml b/publicodes/test/mécanismes/composantes.yaml similarity index 100% rename from test/mécanismes/composantes.yaml rename to publicodes/test/mécanismes/composantes.yaml diff --git a/test/mécanismes/conversion-unité.yaml b/publicodes/test/mécanismes/conversion-unité.yaml similarity index 100% rename from test/mécanismes/conversion-unité.yaml rename to publicodes/test/mécanismes/conversion-unité.yaml diff --git a/test/mécanismes/date.yaml b/publicodes/test/mécanismes/date.yaml similarity index 100% rename from test/mécanismes/date.yaml rename to publicodes/test/mécanismes/date.yaml diff --git a/test/mécanismes/durée.yaml b/publicodes/test/mécanismes/durée.yaml similarity index 100% rename from test/mécanismes/durée.yaml rename to publicodes/test/mécanismes/durée.yaml diff --git a/test/mécanismes/encadrement.yaml b/publicodes/test/mécanismes/encadrement.yaml similarity index 100% rename from test/mécanismes/encadrement.yaml rename to publicodes/test/mécanismes/encadrement.yaml diff --git a/test/mécanismes/expressions.yaml b/publicodes/test/mécanismes/expressions.yaml similarity index 100% rename from test/mécanismes/expressions.yaml rename to publicodes/test/mécanismes/expressions.yaml diff --git a/test/mécanismes/grille.yaml b/publicodes/test/mécanismes/grille.yaml similarity index 100% rename from test/mécanismes/grille.yaml rename to publicodes/test/mécanismes/grille.yaml diff --git a/test/mécanismes/le-maximum-de.yaml b/publicodes/test/mécanismes/le-maximum-de.yaml similarity index 100% rename from test/mécanismes/le-maximum-de.yaml rename to publicodes/test/mécanismes/le-maximum-de.yaml diff --git a/test/mécanismes/le-minimum-de.yaml b/publicodes/test/mécanismes/le-minimum-de.yaml similarity index 100% rename from test/mécanismes/le-minimum-de.yaml rename to publicodes/test/mécanismes/le-minimum-de.yaml diff --git a/test/mécanismes/multiplication.yaml b/publicodes/test/mécanismes/multiplication.yaml similarity index 100% rename from test/mécanismes/multiplication.yaml rename to publicodes/test/mécanismes/multiplication.yaml diff --git a/test/mécanismes/paramètres-nommés.yaml b/publicodes/test/mécanismes/paramètres-nommés.yaml similarity index 100% rename from test/mécanismes/paramètres-nommés.yaml rename to publicodes/test/mécanismes/paramètres-nommés.yaml diff --git a/test/mécanismes/question-conditionelle.yaml b/publicodes/test/mécanismes/question-conditionelle.yaml similarity index 100% rename from test/mécanismes/question-conditionelle.yaml rename to publicodes/test/mécanismes/question-conditionelle.yaml diff --git a/test/mécanismes/recalcul.yaml b/publicodes/test/mécanismes/recalcul.yaml similarity index 100% rename from test/mécanismes/recalcul.yaml rename to publicodes/test/mécanismes/recalcul.yaml diff --git a/test/mécanismes/remplace.yaml b/publicodes/test/mécanismes/remplace.yaml similarity index 100% rename from test/mécanismes/remplace.yaml rename to publicodes/test/mécanismes/remplace.yaml diff --git a/test/mécanismes/rend-non-applicable.yaml b/publicodes/test/mécanismes/rend-non-applicable.yaml similarity index 100% rename from test/mécanismes/rend-non-applicable.yaml rename to publicodes/test/mécanismes/rend-non-applicable.yaml diff --git a/test/mécanismes/régularisation.yaml b/publicodes/test/mécanismes/régularisation.yaml similarity index 100% rename from test/mécanismes/régularisation.yaml rename to publicodes/test/mécanismes/régularisation.yaml diff --git a/test/mécanismes/somme.yaml b/publicodes/test/mécanismes/somme.yaml similarity index 100% rename from test/mécanismes/somme.yaml rename to publicodes/test/mécanismes/somme.yaml diff --git a/test/mécanismes/synchronisation.yaml b/publicodes/test/mécanismes/synchronisation.yaml similarity index 100% rename from test/mécanismes/synchronisation.yaml rename to publicodes/test/mécanismes/synchronisation.yaml diff --git a/test/mécanismes/taux-progressif.yaml b/publicodes/test/mécanismes/taux-progressif.yaml similarity index 100% rename from test/mécanismes/taux-progressif.yaml rename to publicodes/test/mécanismes/taux-progressif.yaml diff --git a/test/mécanismes/toutes-ces-conditions.yaml b/publicodes/test/mécanismes/toutes-ces-conditions.yaml similarity index 100% rename from test/mécanismes/toutes-ces-conditions.yaml rename to publicodes/test/mécanismes/toutes-ces-conditions.yaml diff --git a/test/mécanismes/une-de-ces-conditions.yaml b/publicodes/test/mécanismes/une-de-ces-conditions.yaml similarity index 100% rename from test/mécanismes/une-de-ces-conditions.yaml rename to publicodes/test/mécanismes/une-de-ces-conditions.yaml diff --git a/test/mécanismes/variable-temporelle.yaml b/publicodes/test/mécanismes/variable-temporelle.yaml similarity index 100% rename from test/mécanismes/variable-temporelle.yaml rename to publicodes/test/mécanismes/variable-temporelle.yaml diff --git a/test/mécanismes/variations.yaml b/publicodes/test/mécanismes/variations.yaml similarity index 100% rename from test/mécanismes/variations.yaml rename to publicodes/test/mécanismes/variations.yaml diff --git a/test/period.test.js b/publicodes/test/period.test.js similarity index 99% rename from test/period.test.js rename to publicodes/test/period.test.js index 4316b3869..2439a1d2e 100644 --- a/test/period.test.js +++ b/publicodes/test/period.test.js @@ -4,7 +4,7 @@ import { createTemporalEvaluation, groupByYear, zipTemporals -} from '../source/engine/temporal' +} from '../source/temporal' const neverEnding = value => [{ start: null, end: null, value: value }] describe('Periods : zip', () => { diff --git a/test/ruleUtils.test.js b/publicodes/test/ruleUtils.test.js similarity index 93% rename from test/ruleUtils.test.js rename to publicodes/test/ruleUtils.test.js index 1bf2fc2d8..c9602f2dd 100644 --- a/test/ruleUtils.test.js +++ b/publicodes/test/ruleUtils.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { disambiguateRuleReference, ruleParents } from 'Engine/ruleUtils' +import { disambiguateRuleReference, ruleParents } from '../source/ruleUtils' describe('ruleParents', function() { it('should procude an array of the parents of a rule', function() { diff --git a/test/rules/co2.yaml b/publicodes/test/rules/co2.yaml similarity index 100% rename from test/rules/co2.yaml rename to publicodes/test/rules/co2.yaml diff --git a/test/rules/sasu.yaml b/publicodes/test/rules/sasu.yaml similarity index 100% rename from test/rules/sasu.yaml rename to publicodes/test/rules/sasu.yaml diff --git a/publicodes/test/setupIntl.js b/publicodes/test/setupIntl.js new file mode 100644 index 000000000..6a815ee46 --- /dev/null +++ b/publicodes/test/setupIntl.js @@ -0,0 +1,4 @@ +// Setup Intl in "en" and "fr" for testing +global.Intl = require('intl') +require('intl/locale-data/jsonp/en.js') +require('intl/locale-data/jsonp/fr.js') diff --git a/test/temporal.test.js b/publicodes/test/temporal.test.js similarity index 99% rename from test/temporal.test.js rename to publicodes/test/temporal.test.js index 4316b3869..2439a1d2e 100644 --- a/test/temporal.test.js +++ b/publicodes/test/temporal.test.js @@ -4,7 +4,7 @@ import { createTemporalEvaluation, groupByYear, zipTemporals -} from '../source/engine/temporal' +} from '../source/temporal' const neverEnding = value => [{ start: null, end: null, value: value }] describe('Periods : zip', () => { diff --git a/test/units.test.js b/publicodes/test/units.test.js similarity index 99% rename from test/units.test.js rename to publicodes/test/units.test.js index 4ea4bd50e..9387d4cf6 100644 --- a/test/units.test.js +++ b/publicodes/test/units.test.js @@ -5,7 +5,7 @@ import { inferUnit, parseUnit, removeOnce -} from 'Engine/units' +} from '../source/units' describe('Units', () => { it('should remove the first element encounter in the list', () => { diff --git a/test/utils.test.js b/publicodes/test/utils.test.js similarity index 100% rename from test/utils.test.js rename to publicodes/test/utils.test.js diff --git a/test/variables.test.js b/publicodes/test/variables.test.js similarity index 96% rename from test/variables.test.js rename to publicodes/test/variables.test.js index 0730734a6..ef0ad5a96 100644 --- a/test/variables.test.js +++ b/publicodes/test/variables.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { getSituationValue } from '../source/engine/getSituationValue' +import { getSituationValue } from '../source/getSituationValue' describe('getSituationValue', function() { it('should directly return the value of any rule that specifies a format (i.e currency, duration)', function() { diff --git a/publicodes/tsconfig.json b/publicodes/tsconfig.json new file mode 100644 index 000000000..ed8f712e7 --- /dev/null +++ b/publicodes/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "baseUrl": "source", + "typeRoots": ["source/types"] + }, + "include": ["source"] +} diff --git a/source/webpack.lib.js b/publicodes/webpack.lib.js similarity index 58% rename from source/webpack.lib.js rename to publicodes/webpack.lib.js index 6113da4ba..46a3f9647 100644 --- a/source/webpack.lib.js +++ b/publicodes/webpack.lib.js @@ -1,23 +1,17 @@ const path = require('path') -const { - default: common, - commonLoaders, - styleLoader -} = require('./webpack.common') +const { commonLoaders, styleLoader } = require('./webpack.common') module.exports = { - resolve: common.resolve, entry: './source/engine/index.js', mode: 'development', devtool: 'source-map', output: { path: path.resolve('./dist/'), - filename: 'engine.js', + filename: 'index.js', library: 'Syso', libraryTarget: 'umd', - globalObject: "(typeof window !== 'undefined' ? window : this)" }, module: { - rules: [...commonLoaders(), styleLoader('isomorphic-style-loader')] - } + rules: [...commonLoaders(), styleLoader('isomorphic-style-loader')], + }, } diff --git a/source/components/AttachDictionary.js b/source/components/AttachDictionary.js deleted file mode 100644 index 733132fcf..000000000 --- a/source/components/AttachDictionary.js +++ /dev/null @@ -1,36 +0,0 @@ -import { Markdown } from 'Components/utils/markdown' -import { path } from 'ramda' -import React, { useState } from 'react' -import './Dictionary.css' -import Overlay from './Overlay' - -// On ajoute à la section la possibilité d'ouvrir un panneau d'explication des termes. -// Il suffit à la section d'appeler une fonction fournie en lui donnant du JSX -export let AttachDictionary = dictionary => Decorated => - function withDictionary(props) { - // eslint-disable-next-line react-hooks/rules-of-hooks - const [{ explanation, term }, setState] = useState({ - term: null, - explanation: null - }) - - const onClick = e => { - let term = e.target.dataset['termDefinition'], - explanation = path([term, 'description'], dictionary) - if (!term) return null - setState({ explanation, term }) - } - - return ( -
        - - {explanation && ( - setState({ term: null, explanation: null })}> -
        - -
        -
        - )} -
        - ) - } diff --git a/source/components/Dictionary.css b/source/components/Dictionary.css deleted file mode 100644 index bb16c066a..000000000 --- a/source/components/Dictionary.css +++ /dev/null @@ -1,19 +0,0 @@ -#dictionaryPanel h3 { - color: #333350; - font-weight: bold; - font-size: 125%; -} -#dictionaryPanel blockquote { - font-style: italic; - border-left: 4px solid #eee; - padding-left: 1em; - margin-left: 0; -} -#dictionaryPanel blockquote p { - color: #666; -} -#dictionaryPanel code { - border: 1px solid #aaa; - padding: 0.05em 0.3em; - border-radius: 0.3em; -} diff --git a/source/components/Documentation/Destinataire.css b/source/components/Documentation/Destinataire.css deleted file mode 100644 index d39a3c054..000000000 --- a/source/components/Documentation/Destinataire.css +++ /dev/null @@ -1,26 +0,0 @@ -#destinataire { - border-radius: 3px; - display: flex; - align-items: center; - flex-wrap: wrap; - justify-content: center; -} - -#destinataire a::after { - display: none; -} -#destinataire img { - max-width: 100px; - margin: auto; - display: block; -} -#destinataireName { - text-align: center; - line-height: 1em; -} -#destinataire #calligraphy { - font-size: 150%; - padding: 0.5em; - font-weight: bold; - text-align: center; -} diff --git a/source/components/Documentation/Destinataire.tsx b/source/components/Documentation/Destinataire.tsx deleted file mode 100644 index cd2938539..000000000 --- a/source/components/Documentation/Destinataire.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import possiblesDestinataires from 'Images/destinataires/destinataires.yaml' -import React from 'react' -import { Trans } from 'react-i18next' -import './Destinataire.css' - -export default function Rule({ destinataire }: { destinataire: string }) { - const destinataireData = possiblesDestinataires[destinataire] - - return destinataire && destinataireData ? ( -
        - ) : null -} diff --git a/source/components/Documentation/Header.css b/source/components/Documentation/Header.css deleted file mode 100644 index 0f6ae4792..000000000 --- a/source/components/Documentation/Header.css +++ /dev/null @@ -1,55 +0,0 @@ -#ruleHeader header { - border-radius: 0.3em; - padding: 1em; -} - -#ruleHeader header { - display: flex; - align-items: center; - justify-content: space-between; -} - -#ruleHeader__icon { - font-size: 300%; -} -#rule h1 { - margin: 0.3em 0; -} - -#ruleHeader__content { - display: flex; -} -@media (max-width: 500px) { - #ruleHeader__content { - align-items: center; - flex-direction: column-reverse; - margin: 1rem 0; - } -} -#ruleHeader__description { - flex: 1; - padding-top: 1rem; -} -#ruleHeader__infobox { - padding: 1rem; - padding-top: 0; - max-width: 12rem; -} -.infobox__item { - text-align: center; - display: flex; - flex-direction: column; -} - -#ruleHeader h4 { - margin: 0.6em 0 0.2em; - opacity: 0.6; -} - -#rule pre { - padding: 1em 2em; -} - -#ruleHeader #PeriodSwitch img { - display: none; -} diff --git a/source/components/Documentation/Header.js b/source/components/Documentation/Header.js deleted file mode 100644 index 16834f20f..000000000 --- a/source/components/Documentation/Header.js +++ /dev/null @@ -1,48 +0,0 @@ -import { ThemeColorsContext } from 'Components/utils/colors' -import { path } from 'ramda' -import React, { useContext } from 'react' -import emoji from 'react-easy-emoji' -import { capitalise0 } from '../../utils' -import { Markdown } from '../utils/markdown' -import Destinataire from './Destinataire' -import './Header.css' -import Namespace from './Namespace' - -export default function RuleHeader({ - dottedName, - type, - description, - question, - flatRule, - acronyme, - name, - title, - icon -}) { - const colors = useContext(ThemeColorsContext) - let destinataire = path([type, 'destinataire'])(flatRule) - return ( -
        -
        -
        - -

        - {title || capitalise0(name)} - {acronyme && <> ({acronyme})} -

        -
        - {icon && {emoji(icon)}} -
        -
        -
        - -
        - {destinataire && ( -
        - -
        - )} -
        -
        - ) -} diff --git a/source/components/Documentation/Namespace.css b/source/components/Documentation/Namespace.css deleted file mode 100644 index 3344135e3..000000000 --- a/source/components/Documentation/Namespace.css +++ /dev/null @@ -1,8 +0,0 @@ -#namespace { - padding: 0; - margin: 0; -} - -#namespace li { - display: inline; -} diff --git a/source/components/Documentation/Namespace.tsx b/source/components/Documentation/Namespace.tsx deleted file mode 100644 index ef36a4471..000000000 --- a/source/components/Documentation/Namespace.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { ThemeColorsContext } from 'Components/utils/colors' -import { SitePathsContext } from 'Components/utils/SitePathsContext' -import React, { useContext } from 'react' -import emoji from 'react-easy-emoji' -import { useSelector } from 'react-redux' -import { Link } from 'react-router-dom' -import { DottedName } from 'Rules' -import { capitalise0 } from '../../utils' -import './Namespace.css' -import { EngineContext } from 'Components/utils/EngineContext' - -export default function Namespace({ dottedName }: { dottedName: DottedName }) { - const sitePaths = useContext(SitePathsContext) - const colors = useContext(ThemeColorsContext) - const rules = useContext(EngineContext).getParsedRules() - - return ( -
          - {dottedName - .split(' . ') - .slice(0, -1) - .reduce( - (memo: string[][], next: string) => [ - ...memo, - [...(memo.length ? memo.reverse()[0] : []), next] - ], - [] - ) - .map((fragments: string[]) => { - const ruleName = fragments.join(' . ') as DottedName, - rule = rules[ruleName] - if (!rule) { - throw new Error( - `Attention, il se peut que la règle ${ruleName}, ait été définie avec un namespace qui n'existe pas.` - ) - } - const ruleText = rule.title || capitalise0(rule.name), - style = { color: colors.textColor } - - return ( -
        • - - {rule.icons && {emoji(rule.icons)} } - {ruleText} - - {' › '} -
        • - ) - })} -
        - ) -} diff --git a/source/components/Documentation/Rule.js b/source/components/Documentation/Rule.js deleted file mode 100644 index 38ba99d14..000000000 --- a/source/components/Documentation/Rule.js +++ /dev/null @@ -1,199 +0,0 @@ -import { ThemeColorsContext } from 'Components/utils/colors' -import { EngineContext, useEvaluation } from 'Components/utils/EngineContext' -import { SitePathsContext } from 'Components/utils/SitePathsContext' -import { formatValue } from 'Engine/format' -import mecanisms from 'Engine/mecanisms.yaml' -import { serializeUnit } from 'Engine/units' -import { filter, isEmpty } from 'ramda' -import React, { Suspense, useContext, useState } from 'react' -import emoji from 'react-easy-emoji' -import { Helmet } from 'react-helmet' -import { Trans, useTranslation } from 'react-i18next' -import { Link } from 'react-router-dom' -import Animate from 'Ui/animate' -import { AttachDictionary } from '../AttachDictionary' -import RuleLink from '../RuleLink' -import { Markdown } from '../utils/markdown' -import Algorithm from './Algorithm' -import Examples from './Examples' -import RuleHeader from './Header' -import References from './References' -import { UseDefaultValuesContext } from './UseDefaultValuesContext' - -let LazySource = React.lazy(() => import('./RuleSource')) - -export default AttachDictionary(mecanisms)(function Rule({ dottedName }) { - const [currentExample, setCurrentExample] = useState(null) - const rules = useContext(EngineContext).getParsedRules() - const useDefaultValues = useContext(UseDefaultValuesContext) - const rule = useEvaluation(dottedName, { useDefaultValues }) - const [viewSource, setViewSource] = useState(false) - const { t, i18n } = useTranslation() - let { type, name, acronyme, title, description, question, icon } = rule, - namespaceRules = filter( - rule => - rule.dottedName.startsWith(dottedName) && - rule.dottedName.split(' . ').length === - dottedName.split(' . ').length + 1, - rules - ) - - const renderReferences = ({ références: refs }) => - refs ? ( -
        -

        - Références -

        - -
        - ) : null - - return ( -
        - - - - {(rule.nodeValue || rule.defaultValue || rule.unit) && ( - <> -

        - {rule.nodeValue != null && ( - <> - {formatValue({ ...rule, language: i18n.language })} -
        - - )} - {rule.defaultValue?.nodeValue != null && ( - <> - - Valeur par défaut :{' '} - {formatValue({ - ...rule.defaultValue, - language: i18n.language - })} - -
        - - )} - {rule.nodeValue == null && !rule.defaultValue?.unit && rule.unit && ( - <> - Unité : {serializeUnit(rule.unit)} - - )} -

        - - )} - - - - {viewSource === dottedName ? ( - Chargement du code source...
        }> - - - ) : ( -
        - -
        - )} - - {rule['rend non applicable'] && ( - <> -

        - Rend non applicable les règles suivantes :{' '} -

        -
          - {rule['rend non applicable'].map(ruleName => ( -
        • - -
        • - ))} -
        - - )} - {rule.note && ( - <> -

        Note

        -
        - -
        - - )} - {renderReferences(rule)} - - - {!isEmpty(namespaceRules) && ( - - )} - -
      - ) -}) - -function NamespaceRulesList({ namespaceRules }) { - const colors = useContext(ThemeColorsContext) - const sitePaths = useContext(SitePathsContext) - const useDefaultValues = useContext(UseDefaultValuesContext) - return ( -
      -

      - Pages associées -

      -
        - {Object.values(namespaceRules).map(r => ( -
      • - - {r.title || r.name} - -
      • - ))} -
      -
      - ) -} diff --git a/source/components/Documentation/RulesList.css b/source/components/Documentation/RulesList.css deleted file mode 100644 index 5bed7ab75..000000000 --- a/source/components/Documentation/RulesList.css +++ /dev/null @@ -1,8 +0,0 @@ -#RulesList ul { - margin: 1em auto; - max-width: 860px; - padding: 0; -} -#RulesList li { - list-style: none; -} diff --git a/source/components/Documentation/UseDefaultValuesContext.tsx b/source/components/Documentation/UseDefaultValuesContext.tsx deleted file mode 100644 index 92ae87256..000000000 --- a/source/components/Documentation/UseDefaultValuesContext.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { createContext } from 'react' - -export const UseDefaultValuesContext = createContext(true) diff --git a/source/components/Documentation/index.tsx b/source/components/Documentation/index.tsx deleted file mode 100644 index d2e467fc2..000000000 --- a/source/components/Documentation/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import RulePage from 'Components/RulePage' -import { EngineProvider } from 'Components/utils/EngineContext' -import Engine from 'Engine' -import React from 'react' -import { Route, Switch } from 'react-router' -import { DottedName } from 'Rules' -import RulesList from './RulesList' -import { UseDefaultValuesContext } from './UseDefaultValuesContext' - -type DocumentationProps = { - basePath: string - engine: Engine - useDefaultValues?: boolean -} - -export default function Documentation({ - basePath, - engine, - useDefaultValues = false -}: DocumentationProps) { - return ( - - - - - - - - - ) -} diff --git a/source/components/RuleLink.css b/source/components/RuleLink.css deleted file mode 100644 index a91742c43..000000000 --- a/source/components/RuleLink.css +++ /dev/null @@ -1,3 +0,0 @@ -.rule-link:hover { - opacity: 0.8; -} diff --git a/source/components/RuleLink.tsx b/source/components/RuleLink.tsx deleted file mode 100644 index e6738a13b..000000000 --- a/source/components/RuleLink.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { ThemeColorsContext } from 'Components/utils/colors' -import { SitePathsContext } from 'Components/utils/SitePathsContext' -import { nameLeaf } from 'Engine/ruleUtils' -import { ParsedRule } from 'Engine/types' -import React, { useContext } from 'react' -import { Link } from 'react-router-dom' -import { DottedName } from 'Rules' -import './RuleLink.css' - -type RuleLinkProps = { - dottedName: DottedName - title?: ParsedRule['title'] - className?: string - style?: React.CSSProperties - children?: React.ReactNode -} - -export default function RuleLink({ - dottedName, - className, - title, - style, - children -}: RuleLinkProps) { - const sitePaths = useContext(SitePathsContext) - const { color } = useContext(ThemeColorsContext) - const newPath = sitePaths.documentation.rule(dottedName) - return ( - - {children || title || nameLeaf(dottedName)} - - ) -} diff --git a/source/components/RulePage.css b/source/components/RulePage.css deleted file mode 100644 index 97b40a488..000000000 --- a/source/components/RulePage.css +++ /dev/null @@ -1,8 +0,0 @@ -#RulePage { - margin-top: 2rem; -} -.rule-page__header { - display: flex; - margin-bottom: 0.6rem; - justify-content: space-between; -} diff --git a/source/components/RulePage.tsx b/source/components/RulePage.tsx deleted file mode 100644 index 1fe072289..000000000 --- a/source/components/RulePage.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { goBackToSimulation } from 'Actions/actions' -import { ScrollToTop } from 'Components/utils/Scroll' -import { decodeRuleName } from 'Engine/ruleUtils' -import React, { useContext } from 'react' -import { Trans } from 'react-i18next' -import { connect, useSelector } from 'react-redux' -import { Redirect, useParams } from 'react-router-dom' -import { DottedName } from 'Rules' - -import Rule from './Documentation/Rule' -import './RulePage.css' -import SearchButton from './SearchButton' -import { EngineContext } from './utils/EngineContext' -import { firstStepCompletedSelector } from 'Selectors/simulationSelectors' - -export default function RulePage() { - const parsedRules = useContext(EngineContext).getParsedRules() - const valuesToShow = useSelector(firstStepCompletedSelector) - const { name } = useParams() - const decodedRuleName = decodeRuleName(name ?? '') - - const renderRule = (dottedName: DottedName) => { - return ( -
      - -
      - {valuesToShow ? : } - -
      - -
      - ) - } - - if (!(decodedRuleName in parsedRules)) return - - return renderRule(decodedRuleName as DottedName) -} - -const BackToSimulation = connect(null, { goBackToSimulation })( - // Triggers rerender when the language changes - function BackToSimulation({ goBackToSimulation }) { - return ( - - ) - } -) diff --git a/source/components/SearchBar.tsx b/source/components/SearchBar.tsx deleted file mode 100644 index 15d1319b0..000000000 --- a/source/components/SearchBar.tsx +++ /dev/null @@ -1,277 +0,0 @@ -import { SitePathsContext } from 'Components/utils/SitePathsContext' -import { parentName } from 'Engine/ruleUtils' -import { ParsedRule, ParsedRules } from 'Engine/types' -import { pick, sortBy, take } from 'ramda' -import React, { useContext, useEffect, useState } from 'react' -import FuzzyHighlighter, { Highlighter } from 'react-fuzzy-highlighter' -import { useTranslation } from 'react-i18next' -import { Link, Redirect, useHistory } from 'react-router-dom' -import { DottedName } from 'Rules' -import Worker from 'worker-loader!./SearchBar.worker.js' -import { capitalise0 } from '../utils' -import './SearchBar.css' -import { UseDefaultValuesContext } from './Documentation/UseDefaultValuesContext' - -const worker = new Worker() - -type SearchBarProps = { - rules: ParsedRules - showDefaultList: boolean - finally?: () => void -} - -type Option = Pick, 'dottedName' | 'name' | 'title'> -type Result = Pick, 'dottedName'> - -export default function SearchBar({ - rules, - showDefaultList, - finally: finallyCallback -}: SearchBarProps) { - const sitePaths = useContext(SitePathsContext) - const [input, setInput] = useState('') - const [selectedOption, setSelectedOption] = useState