diff --git a/README.md b/README.md
index 1665f33b85bef4e441351e7170865403156af2a3..6cea4fd42cb69c3deb66fff8587d69b5724dfa80 100644
--- a/README.md
+++ b/README.md
@@ -35,8 +35,8 @@ nav:
           - Architecture: ecolyo/project_architecture/architecture.md
           - Libraries: ecolyo/project_architecture/libraries.md
           - Environments: ecolyo/project_architecture/environments.md
-          - DocTypes: ecolyo/project_architecture/doctypes.md
-          - Remote DocTypes: ecolyo/project_architecture/remote_doctypes.md
+          - Doctypes: ecolyo/project_architecture/doctypes.md
+          - Remote Doctypes: ecolyo/project_architecture/remote_doctypes.md
       - Application:
           - Deploy: ecolyo/application/deploy.md
           - Description: ecolyo/application/description.md
@@ -72,7 +72,7 @@ nav:
               - Libraries: ecolyo/ecolyo-agent/getting_started/libraries.md
           - Functionalities:
               - General: ecolyo/ecolyo-agent/functionalities/general.md
-              - Authentification: ecolyo/ecolyo-agent/functionalities/authentification.md
+              - Authentication: ecolyo/ecolyo-agent/functionalities/authentication.md
               - Routes: ecolyo/ecolyo-agent/functionalities/routes.md
           - Development:
               - Deploy: ecolyo/ecolyo-agent/development/deploy.md
@@ -119,6 +119,7 @@ nav:
   - Konnectors:
       - Introduction: konnectors/index.md
       - Enedis: konnectors/enedis.md
+      - Enedis: konnectors/enedis-sge.md
       - GRDF: konnectors/grdf.md
       - Eau du Grand Lyon: konnectors/egl.md
   - Proxy:
diff --git a/build/dictionary/mkdocs.dic b/build/dictionary/mkdocs.dic
index 5795ce42cd99b71dfbdc05d8a34f63de5f96191a..cc871be061d94bef46899c1eb305161e331f054a 100644
Binary files a/build/dictionary/mkdocs.dic and b/build/dictionary/mkdocs.dic differ
diff --git a/docs/easycozy/tips.md b/docs/easycozy/tips.md
index ea08e8ba26978ba4a446e0bc5c16b41c01f5fe27..fee3bd64a2ee5b33d4f5cd5398ad4ddf3b7c951c 100644
--- a/docs/easycozy/tips.md
+++ b/docs/easycozy/tips.md
@@ -5,12 +5,12 @@
 ### Query data from an instance
 
 For maintenance reason, we sometime need to check data on a specific instance. For that we use postman to send get / post / delete data.
-All posibility are described in the [data section of Cozy documentation](https://docs.cozy.io/en/cozy-stack/data-system/).
+All possibility are described in the [data section of Cozy documentation](https://docs.cozy.io/en/cozy-stack/data-system/).
 
 **Example**
 
 The example will describe how to query userChallenge data from "ecolyotest" instance.
-First, you need to be able to connect to the instance in order to retrive the bearer and the cozysessid.
+First, you need to be able to connect to the instance in order to retrieve the bearer and the cozysessid.
 
 ![Bearer&cozysessid](/img/bearer_cozysessid.png)
 
diff --git a/docs/ecolyo/application/deploy.md b/docs/ecolyo/application/deploy.md
index 90e386d87fdc6e37407961b432cd8e2132b91894..3cb75a9ffd74e60bbc8ce45add045b2df4c8d85e 100644
--- a/docs/ecolyo/application/deploy.md
+++ b/docs/ecolyo/application/deploy.md
@@ -46,13 +46,13 @@ In order to prevent manual action for deployment, a gitlab-runner has been confi
 You can directly use the content of build-test branch to update one instance for test purpose.
 Simply use the dedicated script "update_ecolyo_test.sh <instance_name>" with the targeted instance (from the server).
 By default we use the ecolyotest instance for testing intermediate functionnality.
-For more informations you can check for [Easy Cozy scripts](../../../easycozy/scripts/).
+For more information you can check for [Easy Cozy scripts](../../../easycozy/scripts/).
 
 ## Deploy build-dev branch to all Scaleway instances
 
 You can directly use the content of build-dev branch to update apps on dev environment using scripts (from the server).
 Simply use the dedicated script "update_all_ecolyo_dev.sh" (from the server).
-For more informations you can check for [Easy Cozy scripts](../../../easycozy/scripts/).
+For more information you can check for [Easy Cozy scripts](../../../easycozy/scripts/).
 
 ## Deploy build branch to Cozy
 
diff --git a/docs/ecolyo/application/gitflow.md b/docs/ecolyo/application/gitflow.md
index c21cbbad80b290c2253b39263d1399698f850c10..7a1478be94fde39f3403acffbf76152b724b020c 100644
--- a/docs/ecolyo/application/gitflow.md
+++ b/docs/ecolyo/application/gitflow.md
@@ -49,7 +49,7 @@ The commit contains the following structural **types**:
 - fix
 - feature
 
-In our team organisation we are using IceScrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a `feature` branch name should follow this structure:
+In our team organisation we are using Icescrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a `feature` branch name should follow this structure:
 
 - _features/<number of the User Story\>-<title_of_the_user_story\>_
 
diff --git a/docs/ecolyo/application/mail.md b/docs/ecolyo/application/mail.md
index 482d0aebe2ddcca5e2f7b6e2418ed37950b6ab93..b23a09743fb20a9c4ceb3e12bf1a989f3827b32e 100644
--- a/docs/ecolyo/application/mail.md
+++ b/docs/ecolyo/application/mail.md
@@ -6,7 +6,7 @@ A templating system was needed for the app. In order to make it easy to use and
 
 Handlebars is used as a semantic template motor. It allow us to split email template in order to reuse some parts (header, footer ...)
 
-Mjml is a lib providing a syntax allowing developpers to easly build responsive templates.
+Mjml is a lib providing a syntax allowing developers to easly build responsive templates.
 
 ## Usage
 
@@ -61,12 +61,12 @@ import mjml2html from 'mjml'
 ```
 
 #### Inside the app
-It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why wy need to change the import for mjml lib into :
+It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why we need to change the import for mjml lib into :
 
 ```
 const mjml2html = require('mjml-browser')
 ```
 
 
-### Usefull links
+### Useful links
 - [Mjml live editor](https://mjml.io/try-it-live/bohYnxKkCq-)
diff --git a/docs/ecolyo/application/release.md b/docs/ecolyo/application/release.md
index d2cd7ef332f89f1f2cf300baa6ed25eedfee1ee3..220749a1aa2b8d3b79d017de221a857db0feb7a4 100644
--- a/docs/ecolyo/application/release.md
+++ b/docs/ecolyo/application/release.md
@@ -47,7 +47,7 @@ Don't forget to add release notes in gitlab in *yourProject -> repository -> tag
 You can copy paste the last changelogs in the release notes.
 
 
-## Usefull links
+## Useful links
 [Conventional commit doc](https://www.conventionalcommits.org/en/v1.0.0/)
 
 [Lib link](https://github.com/conventional-changelog/standard-version)
\ No newline at end of file
diff --git a/docs/ecolyo/application/scaffolding.md b/docs/ecolyo/application/scaffolding.md
index e2267cd24a8751f1ca000f447b73ed8816df4210..f14c35248b4769d919ac9f31748d9d42800f3af9 100644
--- a/docs/ecolyo/application/scaffolding.md
+++ b/docs/ecolyo/application/scaffolding.md
@@ -33,4 +33,4 @@ In this section, you will find information about the project file structure and
 | .prettierrc     | Config file for Prettier extension                                                                                     |
 | jest.config.js  | Config file used by Jest for testing the application                                                                   |
 | manifest.webapp | Manifest of the application, used by cozy for the managment of permissions, you can add permissions for doctypes there |
-| tsconfig.json   | Config file for TypeScript                                                                                             |
+| tsconfig.json   | Config file for Typescript                                                                                             |
diff --git a/docs/ecolyo/ecolyo-agent/functionalities/authentification.md b/docs/ecolyo/ecolyo-agent/functionalities/authentication.md
similarity index 78%
rename from docs/ecolyo/ecolyo-agent/functionalities/authentification.md
rename to docs/ecolyo/ecolyo-agent/functionalities/authentication.md
index 7d01d27939081b042c603f931d34116316c0b8fe..a34c0c1db121807d74fa707bb64fef77685a7a88 100644
--- a/docs/ecolyo/ecolyo-agent/functionalities/authentification.md
+++ b/docs/ecolyo/ecolyo-agent/functionalities/authentication.md
@@ -1,4 +1,4 @@
-# Authentification
+# Authentication
 
 This backoffice is meant to be used only by the admins of Ecolyo app and so they need to login to edit the newsletters.
 
@@ -6,5 +6,5 @@ The protocol used to login is OAuth2 with the Authorization Code grant type ([mo
 
 Once an admin is connected, he must call the /whoAmI route to access his XSRF-TOKEN and add it in a header named "XSRF-TOKEN" for all requests going to the backend.
 
-The only routes that can be accessed without authentification are /monthlyReport/year/month and /monthlyReport with GET.
+The only routes that can be accessed without authentication are /monthlyReport/year/month and /monthlyReport with GET.
 They will return all the different sections of a specific or the current newsletter in a single JSON.
\ No newline at end of file
diff --git a/docs/ecolyo/ecolyo-agent/getting_started/launch_local_application.md b/docs/ecolyo/ecolyo-agent/getting_started/launch_local_application.md
index e37aa459b85db79c6e5a788d3b539bf613f725f6..ddc797ad69855c0bbe63a579138dc82fa0c5757c 100644
--- a/docs/ecolyo/ecolyo-agent/getting_started/launch_local_application.md
+++ b/docs/ecolyo/ecolyo-agent/getting_started/launch_local_application.md
@@ -55,7 +55,7 @@ In order to get Backend documentation, please refer directly to the [backend pro
 
 ## Nginx
 
-The nginx server redirects https requests from frontend to the backend on port 1443.
+The nginx server redirects https requests from front-end to the backend on port 1443.
 
 It has two configuration files :
 
diff --git a/docs/ecolyo/ecolyo-agent/getting_started/libraries.md b/docs/ecolyo/ecolyo-agent/getting_started/libraries.md
index 83db280f4761a643da2437eb36232d2428967110..d16c2433c1e6f4e55530e7257d1bffd09e67a057 100644
--- a/docs/ecolyo/ecolyo-agent/getting_started/libraries.md
+++ b/docs/ecolyo/ecolyo-agent/getting_started/libraries.md
@@ -31,11 +31,11 @@ Lodash'modular method are great for:
 
 Testing library
 
-It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product.
+It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product.
 
 ## Sass
 
-CSS preprocessor
+CSS Preprocessor
 
 It allows us to easily manage large CSS files and split across different files.
 It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.
diff --git a/docs/ecolyo/ecolyo-agent/getting_started/setup_your_environment.md b/docs/ecolyo/ecolyo-agent/getting_started/setup_your_environment.md
index 0443d3be2c6910629bddcacfd0c1bfb9a69c4a80..336fd04b2f8dbcec2c12645545ea658061dd79b7 100644
--- a/docs/ecolyo/ecolyo-agent/getting_started/setup_your_environment.md
+++ b/docs/ecolyo/ecolyo-agent/getting_started/setup_your_environment.md
@@ -78,7 +78,7 @@ Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
 
 ## Yarn
 
-Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager.
+Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager.
 Installation for yarn can be found here: [Installation of Yarn](https://classic.yarnpkg.com/fr/docs/install/).
 
 ## Docker
diff --git a/docs/ecolyo/ecolyo-agent/introduction.md b/docs/ecolyo/ecolyo-agent/introduction.md
index 617f74eaeb673959b00374eba5f9052c9a660fde..c1489cafe37073c932d366227d6dce5fe65a898c 100644
--- a/docs/ecolyo/ecolyo-agent/introduction.md
+++ b/docs/ecolyo/ecolyo-agent/introduction.md
@@ -1,12 +1,12 @@
 Ecolyo-Agent is a backoffice for the Ecolyo app that allows to create and edit content for the newsletters sent to the users
 
-This project is split into two parts: backend and frontend; each has its own repository 
+This project is split into two parts: backend and front-end; each has its own repository 
 
 !!! info ""
-    If you are a new developper tasked to work on this project, check the [setup your environment](./getting_started/setup_your_environment.md) and [launch the application on local](./getting_started/launch_local_application.md) to start the application.
+    If you are a new developer tasked to work on this project, check the [setup your environment](./getting_started/setup_your_environment.md) and [launch the application on local](./getting_started/launch_local_application.md) to start the application.
 
 ## Repositories
 
 [Ecolyo-Agent backend gitlab repository](https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server)
 
-[Ecolyo-Agent frontend gitlab repository](https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client)
\ No newline at end of file
+[Ecolyo-Agent front-end gitlab repository](https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client)
\ No newline at end of file
diff --git a/docs/ecolyo/functionalities/analysis.md b/docs/ecolyo/functionalities/analysis.md
index 16fcbafb4649e37477337b4dad537dd96b28471c..8a311049bbdaba5f8c0bc0c6e574979b9171f7c5 100644
--- a/docs/ecolyo/functionalities/analysis.md
+++ b/docs/ecolyo/functionalities/analysis.md
@@ -7,7 +7,7 @@ It allows him to compare his consumption with the previous month and also with a
 
 ### Graph
 
-On the left side, the user can see his consumption for the konnected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate.
+On the left side, the user can see his consumption for the connected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate.
 
 Also, when user has the possibility to switch the comparison with the average profile or the ideal profile. For now, the ideal profile just represents the average profile's consumption minus 10%.
 
diff --git a/docs/ecolyo/functionalities/challenge.md b/docs/ecolyo/functionalities/challenge.md
index f8e7b26056e0e141b7dc004ce72f70b2e4b2f3a5..9eeead5426734f6f1034855a137b09d3686ff5e4 100644
--- a/docs/ecolyo/functionalities/challenge.md
+++ b/docs/ecolyo/functionalities/challenge.md
@@ -1,4 +1,4 @@
-This section explain all the functionnalities in the challenge part
+This section explain all the functionalities in the challenge part
 
 ## Quiz
 
@@ -154,7 +154,7 @@ singleFluid = false
 
 #### Wrong answers
 
-After defining the right answer, two randows answers are generated depending of the custom question type:
+After defining the right answer, two random answers are generated depending of the custom question type:
 
 - type DATE
 
diff --git a/docs/ecolyo/functionalities/consumption.md b/docs/ecolyo/functionalities/consumption.md
index c819ca9e5ca0e607051cf31550765114c0409906..287e5e8ab28d6549a3ebf082ab74ac564f99d164 100644
--- a/docs/ecolyo/functionalities/consumption.md
+++ b/docs/ecolyo/functionalities/consumption.md
@@ -2,7 +2,7 @@
 
 Ecolyo allow user to see its consumption in two way:
 
-- globally with the Mutlifluid view that displays euro consumptions
+- globally with the mutlifluid view that displays euro consumptions
 - more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu
 
 All consumption information are retrieved and calculated by services from the application.
@@ -204,8 +204,8 @@ This component shows the konnector's state and allows the user to connect, delet
 
 ### Rules
 
-- If the fluid is konnected, this component will shows the konnector state at the end of the consumption page
-- If the fluid is not konnected, it will show the connection form
+- If the fluid is connected, this component will shows the konnector state at the end of the consumption page
+- If the fluid is not connected, it will show the connection form
 - If the konnector is in error or its data is outdated, it will display the number of days since the data is outdated
 - If the error is a login error (eg: user consent is revocated), it will show a specific message
 - If the data is outdated but the user has already triggered an update today, we will show a message that informs the user that the issue is probably related to the energy provider
diff --git a/docs/ecolyo/functionalities/dacc.md b/docs/ecolyo/functionalities/dacc.md
index d14a6c5d43d66322283ff46a1ad39ed0ecd536a2..c2400ce07754d57e0ae1233e94cdd37396b07412 100644
--- a/docs/ecolyo/functionalities/dacc.md
+++ b/docs/ecolyo/functionalities/dacc.md
@@ -197,7 +197,7 @@ cd ./scripts
 node server.js
 ```
 
-Then you are finaly ready to test ! Just run the following :
+Then you are finally ready to test ! Just run the following :
 
 ```sh
 yarn build-dev:browser; yarn run cozy-konnector-dev -m .\manifest.webapp .\build\services\aggregatorUsageEvents\ecolyo.js
diff --git a/docs/ecolyo/functionalities/ecogesture.md b/docs/ecolyo/functionalities/ecogesture.md
index 44569b02ca5bf5bfc1b91223af242f564744b632..850965a043442f94779f04f47a9813f725fa609a 100644
--- a/docs/ecolyo/functionalities/ecogesture.md
+++ b/docs/ecolyo/functionalities/ecogesture.md
@@ -92,7 +92,7 @@ Once user has completed his profile ecogesture through the form, he has the poss
 - User can go back and correct his answer at any time
 - User can stop the process at any time, hist answer will be saved ad the next time he will open the selection, a new stack of 10 ecogesture is made (for example, user stops at 4/10, the next time he opens the selection it will be 4/14)
 - If user chooses to select manually an ecogesture outside of the selection tunnel (through the 'all' tab), this ecogesture will be removed from the list it was existing in it.
-- If user chosses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), thoose ecogestures won't be purposes again in the selection tunnel.
+- If user choses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), these ecogestures won't be purposes again in the selection tunnel.
 - User can't use the back arrow on the first ecogesture of selection list
 
 Once the whole process is done, the user has no possibility to do it again through the tinder-like selection, but he can still edit his ecogestures manually from the various tabs.
diff --git a/docs/ecolyo/functionalities/feedback.md b/docs/ecolyo/functionalities/feedback.md
index 4a3b5ea77f5322e40f208d4cb266076b347b6100..f789cd10c3f4f5dcd86466f7f0860f798044fa04 100644
--- a/docs/ecolyo/functionalities/feedback.md
+++ b/docs/ecolyo/functionalities/feedback.md
@@ -6,7 +6,7 @@ Users can send a feedback in the application, the feedback's receiver is defined
 
 The user has the possibility to add an image to a feedback.
 
-The email informations are created in the _sendEmail_ function and the mailData respects this scheme :
+The email information are created in the _sendEmail_ function and the mailData respects this scheme :
 
 ```js
 const mailData = {
diff --git a/docs/ecolyo/functionalities/initialization.md b/docs/ecolyo/functionalities/initialization.md
index bce2a11dbe20407b556bca986fe9e0e553b97ba7..93e493f6233404db77972158afc2caa4c1ecb05d 100644
--- a/docs/ecolyo/functionalities/initialization.md
+++ b/docs/ecolyo/functionalities/initialization.md
@@ -89,7 +89,7 @@ You can see more about relationships on [cozy documentation](https://docs.cozy.i
 
 ### UserData creation
 
-We create a userData and store it in the couchDB under the doctype userData name '**com.grandlyon.ecolyo.userDataName'.** During this process, the objects related to the dataEntity will be be converted to an user version which contains informations about the user(example: user progress, the fluids connected and so on).
+We create a userData and store it in the couchDB under the doctype userData name '**com.grandlyon.ecolyo.userDataName'.** During this process, the objects related to the dataEntity will be be converted to an user version which contains information about the user(example: user progress, the fluids connected and so on).
 
 To illustrate this, let's show an example of the conversion of duelEntity to UserDuel :
 
diff --git a/docs/ecolyo/functionalities/profile_type.md b/docs/ecolyo/functionalities/profile_type.md
index 00bdeef20c8cecc9c12cbd5bf9f4518154c59dae..ad94fd4f031ec7e3d2d9a6882a95d5770ae3f32d 100644
--- a/docs/ecolyo/functionalities/profile_type.md
+++ b/docs/ecolyo/functionalities/profile_type.md
@@ -2,7 +2,7 @@ This section explains the profileType creation process in order to make differen
 
 ## Profile type data
 
-The profileType data are stored in the profile doctype and includes the following informations :
+The profileType data are stored in the profile doctype and includes the following information :
 
 ```jsx
 {
@@ -58,7 +58,7 @@ By default, current month and year will be selected.
 If current year is not yet completed (december not reached), month dropdown menu will only propose past and present months for this year.
 
 When finishing, before the new profileType is saved. Checks if other profileTypes exist on the period between selected month/year and present day.
-- If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some informations before, this new profiletype will be more accurate). Then save profileType on given month/year.
+- If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some information before, this new profiletype will be more accurate). Then save profileType on given month/year.
 - If no other profileTypes are found, save profileType on given month/year.
 
 ## Profile type entity service
@@ -144,14 +144,14 @@ Here is an example of a MonthlyForecast, which is the only function directly cal
 
 In these data, the load is in kWh for gaz and electricity (fluidtype 0 and 2) and in L for water. Value and totalValue are given in euros. The different consumption are distributed to their corresponding fluidType according to the variables **_warmingFluid, hotWaterFluid, cookingFluid _**. For example, if the cookingFluid is gaz, then its value will be stored in the fluidType 2 and nulled in the others.
 
-Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personnal consumption, so it doesn't takes place in the calculation.
+Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personal consumption, so it doesn't takes place in the calculation.
 
 ## DJU
 
 The method **fetchDJU(month:number)** tries to fetch the daily dju from the datagrandlyon API trough a remote doctype named _org.ecolyo.dju_.
 The data returned by this API are gathered by the lyon-bron-sta The API returns dju by day for a given month, so we add them to return a monthly dju. If remote doctype fails or return a null value, we returns instead the default dju stored in _heating.json_
 
-Usefull tips while working with this API :
+Useful tips while working with this API :
 
 - Do not pass a Content-Type while requesting, it will returns error
 - While requesting from a cozy instance, if you get errors, you will get errors from the cozy stack and not directly from the API, which leads to weird cases :
diff --git a/docs/ecolyo/functionalities/terms.md b/docs/ecolyo/functionalities/terms.md
index afabb8defa2d89975db51e0bc50a09224aacf3b1..016dc06038c9e9bcf12d0cec6ae311b14dcb4c1e 100644
--- a/docs/ecolyo/functionalities/terms.md
+++ b/docs/ecolyo/functionalities/terms.md
@@ -16,9 +16,9 @@ The only public routes are :
 
 ### Terms managment
 
-We check the terms acceptation in the **SplashScreen** while the application is initializing, if there is no consent (first connexion), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page.
+We check the terms acceptation in the **splash screen** while the application is initializing, if there is no consent (first connection), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page.
 
-For the full terms acceptation process, the user has to check the two checboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value _accepted_ to true. So he can access now the entire application.
+For the full terms acceptation process, the user has to check the two checkboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value _accepted_ to true. So he can access now the entire application.
 We store in user's profile a boolean _showConsentModal_ that allows the app to know about the consent status.
 
 If there is a consent update, two cases are possible : 
@@ -31,7 +31,7 @@ The version number of the last terms is stored in the **config.json** file. If t
 
 ### Global state
 
-Once the verification done in the **SplashScreen**, the last term state is stored in the redux store under the ecolyo.global state.
+Once the verification done in the **splash screen**, the last term state is stored in the redux store under the ecolyo.global state.
 
 The model is the following :
 
@@ -42,4 +42,4 @@ The model is the following :
   },
 ```
 
-Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connexion or to case the last accepted term version is uptodate.
\ No newline at end of file
+Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connection or to case the last accepted term version is up to date.
\ No newline at end of file
diff --git a/docs/ecolyo/getting_started/launch_local_application.md b/docs/ecolyo/getting_started/launch_local_application.md
index b361eaa2ec2f2b2765bd6a1e6d5b3f69ba0569b6..bc72e993b8978266fb307c02f9093055fb3bce67 100644
--- a/docs/ecolyo/getting_started/launch_local_application.md
+++ b/docs/ecolyo/getting_started/launch_local_application.md
@@ -35,24 +35,6 @@ If the application starts successfully you should obtain the following message:
 
 Once the application is started, run the easy-cozy stack with docker.
 
-### Run easy-cozy dev stack
-
-The dev stack will contain the cozy-stack with some default applications and konnectors and allow you to run this stack locally.
-
-First login to the forge registry:
-
-```
-docker login registry.forge.grandlyon.com
-```
-
-You will need to enter for credentials.
-
-Next pull the last image of the dev stack:
-
-```
-docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env:latest
-```
-
 #### On windows and linux
 
 Launch the stack with the following command:
diff --git a/docs/ecolyo/getting_started/launch_local_konnector.md b/docs/ecolyo/getting_started/launch_local_konnector.md
index 72eccbd46e1082e5505944347cc7b4171ad786f0..c2a670ac0d90dbf87526907a8f0635b847858cd1 100644
--- a/docs/ecolyo/getting_started/launch_local_konnector.md
+++ b/docs/ecolyo/getting_started/launch_local_konnector.md
@@ -12,7 +12,7 @@ Simply launch it by typing:
 `yarn standalone`
 
 This command will create a **konnector-dev-config.json** file if it was not in your project folder before.
-This file needs to hold all the informations transmitted by the cozy stack when the konnector runs by default 
+This file needs to hold all the information transmitted by the cozy stack when the konnector runs by default 
 
 - baseUrl
 - apiAuthKey
diff --git a/docs/ecolyo/project_architecture/doctypes.md b/docs/ecolyo/project_architecture/doctypes.md
index 1ff0c2d31d22eec4c497dbcd8d3a1875a0cb9a22..7d6760dcc0b54bf6a4d46ec9f92103a3cf972e58 100644
--- a/docs/ecolyo/project_architecture/doctypes.md
+++ b/docs/ecolyo/project_architecture/doctypes.md
@@ -662,7 +662,7 @@ This doctype is used to store the enedis maxpower values retrieved by the konnec
 
 | Field  | Type   | Description                                                      |
 | ------ | ------ | ---------------------------------------------------------------- |
-| load   | number | maxPower in kVA                                             |
+| load   | number | maxpower in kVA                                             |
 | minute | number | minute of the date     |
 | hour   | number | hour of the date |
 | day    | number | day of the date       |
@@ -689,4 +689,4 @@ This doctype is used to store the enedis monthly analysis, it includes the month
 | month  | number         | Month of the analysis               |
 | year  | number         | Year of the analysis |
 | minLoad | number or null         | Minimum half hour load of the month                                                                 |
-| maxPower | number or null           | Max power value of the month                                                               |
+| maxpower | number or null           | Max power value of the month                                                               |
diff --git a/docs/ecolyo/project_architecture/environments.md b/docs/ecolyo/project_architecture/environments.md
index 29d840d5a05afd89f0464a2ee94ce0f22513a259..7a0f3b06c645701143574900c1bd7dfe26fa1b37 100644
--- a/docs/ecolyo/project_architecture/environments.md
+++ b/docs/ecolyo/project_architecture/environments.md
@@ -32,7 +32,7 @@ Let's see more details in the [dedicated section](../../easycozy/scripts.md).
 
 ### Proxy
 
-Konnector for Ecolyo need proxy for the OAuth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy
+Konnector for Ecolyo need proxy for the Oauth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy
 
 The proxy is written in Go language. The "main.go" file containt all the source code and also the default variables. 
 Default variables are the one used for the dev environment but we will overwrite them for the production.
@@ -60,7 +60,7 @@ Fully managed by Cozy team.
 
 ### Proxy
 
-A dedicated proxy is deployed on Cozy side to allow konnector to make the OAuth dance. 
+A dedicated proxy is deployed on Cozy side to allow konnector to make the Oauth dance. 
 The proxy deployed is based on the project available on the GitLab but variables are overwritten using flags by the Cozy team in order to fit to the environment.
 
 For each modification in production, it needs:
diff --git a/docs/ecolyo/project_architecture/libraries.md b/docs/ecolyo/project_architecture/libraries.md
index 227c6e9615e03088c8b3f95b345277decaee028f..f75be77990cb616af37fd1c1776b8dfead16f6b5 100644
--- a/docs/ecolyo/project_architecture/libraries.md
+++ b/docs/ecolyo/project_architecture/libraries.md
@@ -46,7 +46,7 @@ Wrapper for Javascript dates and times.
 
 Testing library
 
-It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product.
+It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product.
 
 ## Enzyme
 
@@ -56,7 +56,7 @@ It makes it easier to test your React Components' output. You can also manipulat
 
 ## Sass
 
-CSS preprocessor
+CSS Preprocessor
 
 It allows us to easily manage large CSS files and split across different files.
 It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.
diff --git a/docs/ecolyo/services/aggregator_usage_events.md b/docs/ecolyo/services/aggregator_usage_events.md
index 3cccc74e1003c31ff6c67a942e6b2ecf3ca64de1..86cbf8ad2b7803f4abf9a859af0536db0147b498 100644
--- a/docs/ecolyo/services/aggregator_usage_events.md
+++ b/docs/ecolyo/services/aggregator_usage_events.md
@@ -8,7 +8,7 @@ The service will run each day at [TO BE DEFINED], as defined in the manifest:
       "trigger": "[TO BE DEFINED]"
     }
 ```
-# Main responsabilities of the service
+# Main responsibilities of the service
 
 The service is responsible of :
 
diff --git a/docs/ecolyo/services/consumption_alert.md b/docs/ecolyo/services/consumption_alert.md
index 252181c04d77ef19b52a62e5fb1e718b8200038f..0cd1821c9578fa15f04b69e1a43f5261297a86a6 100644
--- a/docs/ecolyo/services/consumption_alert.md
+++ b/docs/ecolyo/services/consumption_alert.md
@@ -8,9 +8,9 @@ The service will run everyday at 10.00 am, as defined in the manifest:
     "trigger": "@cron 0 3 * * *"
     }
 ```
-# Main responsabilities of the service
+# Main responsibilities of the service
 
-The service is reponsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel).
+The service is responsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel).
 
 For now it only monitors water consumptions.
 
diff --git a/docs/ecolyo/services/enedis_halfhour_monthly_analysis.md b/docs/ecolyo/services/enedis_halfhour_monthly_analysis.md
index 79295a547e113196905244d8de21d3aa82364ee0..51c532e0e04ab1f9f5a25658d64c168de7b91092 100644
--- a/docs/ecolyo/services/enedis_halfhour_monthly_analysis.md
+++ b/docs/ecolyo/services/enedis_halfhour_monthly_analysis.md
@@ -8,9 +8,9 @@ The service will run everyday 3rd of month at 8.00 am, as defined in the manifes
       "trigger": "@cron 0 0 8 3 * *"
     }
 ```
-# Main responsabilities of the service
+# Main responsibilities of the service
 
-The service is reponsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype *com.grandlyon.enedis.monthly.analysis.data*
+The service is responsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype *com.grandlyon.enedis.monthly.analysis.data*
 
 Main steps are the following :
 
@@ -34,7 +34,7 @@ This function is charged to do the following things :
 
 - Filter days in 2 parts : weekdays and week end days
 
-- For each half-hour data push the data in a global 2dimensionnal array ; there is 2 global array, one for week-end days and the other for weekdays
+- For each half-hour data push the data in a global 2 dimensional array ; there is 2 global array, one for week-end days and the other for weekdays
 
 - At the point we have 2 global array with each 48 arrays filled with the corresponding values. To illustrate this, here is an example of how the data is sorted : 
 
@@ -49,8 +49,8 @@ weekEndValuesArray : [
 ```
 - Once the array is filled with all available values, we just have to calculate the average for each half-hour step
 
-- The **minimum value** is calculated by the *getMonthMinLoad* function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplicated with 48 (the number of half hour entries in a day) and with the number of days in the month.
-- The **maxPower** value is fetched from the doctype *com.grandlyon.enedis.maxpower*, the value is stored on a daily basis, so take the maximum value for the given month.
+- The **minimum value** is calculated by the *getMonthMinLoad* function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplied by 48 (the number of half hour entries in a day) and with the number of days in the month.
+- The **maxpower** value is fetched from the doctype *com.grandlyon.enedis.maxpower*, the value is stored on a daily basis, so take the maximum value for the given month.
 - The result is stored in *com.grandlyon.enedis.monthly.analysis.data* according to the following model : 
 
 ```
@@ -58,7 +58,7 @@ EnedisMonthlyAnalysisData {
   weekDaysHalfHourAverageValues: number[]
   weekEndDaysHalfHourAverageValues: number[]
   minimumLoad: number
-  maxPower: number
+  maxpower: number
   month: number
   year: number
 }
diff --git a/docs/ecolyo/services/index.md b/docs/ecolyo/services/index.md
index 79b1abb8bbfdfa9c4000c45122401c94ec9e9ff6..453f104ff3d212f92df539f7486db1a0cada8350 100644
--- a/docs/ecolyo/services/index.md
+++ b/docs/ecolyo/services/index.md
@@ -1,6 +1,6 @@
 In order to build an automated task within our cozy-stack, we can create *services* which are javascript files called from a trigger job.
 
-For instance on Ecolyo, to schedule a mail that alert the user that a new **monthly report** is available in the application, we add a trigger that is launched every month with a *cron* attribute. On that trigger we link a .js script then we instanciate this script with cozy-client.
+For instance on Ecolyo, to schedule a mail that alert the user that a new **monthly report** is available in the application, we add a trigger that is launched every month with a *cron* attribute. On that trigger we link a .js script then we instantiate this script with cozy-client.
 
 # Configuration
 ## Manifest
diff --git a/docs/ecolyo/services/monthly_report_notification.md b/docs/ecolyo/services/monthly_report_notification.md
index 8465862fdabe35e6fde81b7e28acaa5763bc6f6c..8ffebc98b5671bc2bf5504bd1b1f0683457103bf 100644
--- a/docs/ecolyo/services/monthly_report_notification.md
+++ b/docs/ecolyo/services/monthly_report_notification.md
@@ -8,9 +8,9 @@ The service will run the 3rd of each month at 10.00 am, as defined in the manife
       "trigger": "@cron 0 0 10 3 * *"
     }
 ```
-# Main responsabilities of the service
+# Main responsibilities of the service
 
-The service is reponsible of sending a mail to user to warn him about the availability of a new information in the Analyse.
+The service is responsible of sending a mail to user to warn him about the availability of a new information in the Analyse.
 
 Main steps are the following:
  - Check the "sendReportNotification" attribute in the com.grandlyon.ecolyo.profile doctype. If true, service will continue, else it will stop.
diff --git a/docs/index.md b/docs/index.md
index bc5cbbd43dc959d19da50529561cc6ec8dd46c0e..83fc5c56b0c2eb416f83e82f76ea5efdfed6bd31 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -11,7 +11,7 @@ Name                               | Required | Details
 ---------------------------------- | -------- | -------
 [Node](https://nodejs.org/en/download/) | Yes      | Node 16 must be installed as it is the version that runs on the official cozystack.
 [Yarn](https://classic.yarnpkg.com/en/docs/install)    | Yes  | Yarn is our projects package manager.
-[Docker](https://www.docker.com/get-started) | Yes |  See [cozystack]() for more informations.
+[Docker](https://www.docker.com/get-started) | Yes |  See [cozystack]() for more information.
 [Docker-compose](https://docs.docker.com/compose/install/) | Yes
 [WSL](index.md#wsl) | No | Required for windows users.
 
@@ -83,7 +83,7 @@ If you install the MSI from [wsl2kernel](https://aka.ms/wsl2kernel). Once you ha
 
 #### Install your Linux distribution
 
-After reboot, open the microsoft store and install the distribution of your choice, for instance: ==Ubuntu 20.04 LTS==. Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.
+After reboot, open the microsoft store and install the distribution of your choice, for instance: ==Ubuntu 20.04 lts==. Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.
 
 To make sure it's correctly installed and working, you can open Powershell and paste the following command :
 
@@ -120,7 +120,7 @@ Now you should see the name of your distribution in the list.
     $ npm --version
     ```
 
-6. To Downlaod and Setup Yarn
+6. To Download and Setup Yarn
     ```console
     $ sudo apt install yarn
     ```
diff --git a/docs/konnectors/enedis-sge.md b/docs/konnectors/enedis-sge.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab302a50f6e6c8c85e817a809dec259b2f69cd00
--- /dev/null
+++ b/docs/konnectors/enedis-sge.md
@@ -0,0 +1,119 @@
+This konnector fetches consumptions measures from Enedis SGE SOAP API. 
+
+You should also check Cozy's official documentations for konnectors :
+[https://docs.cozy.io/en/tutorials/konnector/getting-started/](https://docs.cozy.io/en/tutorials/konnector/getting-started/)
+
+# Enedis SGE Konnector
+
+!!! warning "This konnector is in a POC state"
+
+## Enedis context
+
+The API's used by this konnector are the one used by all energy providers (edf, total...), this one is supposed to have a high availability and disponibility. Contrary to enedis oauth konnector, this is a regular auth konnector.
+
+## Technical overview
+
+### Lib used 
+
+- xml2js: Lib allowing easy parsing to json
+- easy-soap-request: Lib making soap request
+
+### WSO2
+
+For now enedis API's are proxied by WSO1 api manager. You can find documentation and devportal [here](https://apis.grandlyon.fr/devportal).
+
+### Scaffolding 
+
+- Aggregate.js: file holding method responsible for month and year aggregation 
+- parsing.js: contain all methods for xml to json parsing and data formating
+- request.js: hold SGE query methods 
+- types.js: file containing type definition to allow js type check.
+- index.js: main file where default konnector methods are launch (start, ...)
+
+### ts-check
+
+In order to have better comfort while coding, we have enable ts-checking with vs-code. The verification is based on js-doc, please take time to maintain the js-doc.
+
+!!! note "ts-check"
+    The ts-check is none blocking. It will only put information in vs-code ide.
+
+
+### Konnector Methods
+| Method | Description |
+| ------ | ------ |
+| start | Main method of konnector. Handle global flow and init method with prvided params |
+| getDataStartDate | Retrieve user contract *startDate* in order to request an accurate time range of data |
+| getData | Get daily data |
+| getMaxPowerData | Get daily Max Power data |
+| getHalfHourData | Get half-hour data |
+| processData | Given a doctype, parse and format data before storing and aggregating |
+| processStartDate | Save startDate and process queries time range |
+| storeData | Save data to user's cozy |
+| agregateMonthAndYearData | Sum daily data for months and years |
+
+## Dataflow
+
+### Overview
+
+[Lien du schéma](https://whimsical.com/sge-tech-DxbYM8DdajRjTr6WZat1bV)
+
+### Authentication
+
+**TODO: Write this part when full implementation will be done.**
+
+Informations required: 
+
+- Name
+- Surname
+- PointID (PDL)
+- Full address 
+
+### Fetch Data
+
+In order to get data from the SGE API we have to request the following route :
+
+1. Get user contrat startDate
+
+Method : **POST**
+
+Data Route : **enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0**
+
+```xml
+<soapenv:Body>
+    <v2:consulterDonneesTechniquesContractuelles>
+        <pointId>${pointId}</pointId>
+        <loginUtilisateur>${userLogin}</loginUtilisateur>
+        <autorisationClient>true</autorisationClient>
+    </v2:consulterDonneesTechniquesContractuelles>
+</soapenv:Body>
+```
+
+2. Get daily data
+3. Get Max Power data
+4. Get Half-hour data
+
+The same endpoint is used to get the data. The soap body is the follwing:
+
+Method : **POST**
+
+Data Route : **enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0**
+
+```xml
+<soapenv:Body>
+    <v2:consulterMesuresDetaillees>
+        <demande>
+            <initiateurLogin>${userLogin}</initiateurLogin>
+            <pointId>${pointId}</pointId>
+            <mesuresTypeCode>${mesureType}</mesuresTypeCode>
+            <grandeurPhysique>${unit}</grandeurPhysique>
+            <soutirage>true</soutirage>
+            <injection>false</injection>
+            <dateDebut>${startDt}</dateDebut>
+            <dateFin>${endDt}</dateFin>
+            <mesuresCorrigees>false</mesuresCorrigees>
+            <accordClient>true</accordClient>
+        </demande>
+    </v2:consulterMesuresDetaillees>
+</soapenv:Body>
+```
+
diff --git a/docs/konnectors/enedis.md b/docs/konnectors/enedis.md
index 887f56e5e7c5f99b5b95f7e30d3c9d362d88806d..d7d680876fe744b9edece6a9fb7c110ee459b05a 100644
--- a/docs/konnectors/enedis.md
+++ b/docs/konnectors/enedis.md
@@ -1,4 +1,4 @@
-This konnector fetches consumptions measures from Enedis API. This is an Oauth Konnector, meaning the authentification performed to access all data is made following an Oauth2 protocol.
+This konnector fetches consumptions measures from Enedis API. This is an Oauth Konnector, meaning the authentication performed to access all data is made following an Oauth2 protocol.
 You can clone the project [here](https://forge.grandlyon.com/web-et-numerique/llle_project/enedis-konnector).
 
 You should also check Cozy's official documentations for konnectors :
@@ -10,7 +10,7 @@ You should also check Cozy's official documentations for konnectors :
 The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the [proxy](/proxy/description/) documentation to fully understand all the interactions that will be told below.
 
 All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data.
-On its first launch, following the Oauth Client Connect authentification.
+On its first launch, following the Oauth Client Connect authentication.
 
 - The cozy stack calls the **authentification_endpoint** and start the oauth protocol, see [proxy doc](/proxy/description/).
 - The account has now an access_token and an id_token from the oauth call
@@ -27,7 +27,7 @@ This token holds several meta datas, including the usage_point_id (id of user's
 - API Url for Production : [https://gw.prd.api.enedis.fr](https://gw.prd.api.enedis.fr)
 - API url for Development : [https://gw.hml.api.enedis.fr](https://gw.hml.api.enedis.fr)
 
-Once you've finished the OAuth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo:
+Once you've finished the Oauth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo:
 
 Method : **GET**
 
@@ -69,13 +69,13 @@ For more information about Datahub-Enedis API, checkout the [Datahub documentati
 | launchLoadDataProcess         | Launch process to handle load data                                                                                                                                                                                                                                                        |
 | getLoadData                   | Retrieve data from the API. Format: `{ value: "W", "date": "YYYY-MM-DD hh:mm:ss" }`                                                                                                                                                                                                       |
 | processData                   | Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data                                                                                                                                                                 |
-| agregateMonthAndYearData      | Agregate data from daily data to monthly and yearly data                                                                                                                                                                                                                                  |
-| agregateHourlyData            | Agregate data from load data (every 30 min) to Hourly data                                                                                                                                                                                                                                |
+| aggregateMonthAndYearData      | Aggregate data from daily data to monthly and yearly data                                                                                                                                                                                                                                  |
+| aggregateHourlyData            | Aggregate data from load data (every 30 min) to Hourly data                                                                                                                                                                                                                                |
 | storeData                     | Save data in the right doctype db and prevent duplicated keys                                                                                                                                                                                                                             |
 | formateData                   | Format data for DB storage and remove bad data                                                                                                                                                                                                                                            |
-| buildAgregatedData            | Retrieve and remove old data for a specific doctype and return an array of agregated data                                                                                                                                                                                                 |
+| buildAggregatedData            | Retrieve and remove old data for a specific doctype and return an array of aggregated data                                                                                                                                                                                                 |
 | buildDataFromKey              | Format an entry for DB storage using key and value. For year doctype: key = "YYYY". For month doctype: key = "YYYY-MM"                                                                                                                                                                    |
-| getMaxPower              | Retrieve data from the maxPower API. Format: `{ value: "kVA", "date": "YYYY-MM-DD" }`                                                                           |
+| getMaxPower              | Retrieve data from the maxpower API. Format: `{ value: "kVA", "date": "YYYY-MM-DD" }`                                                                           |
 | isHistoryLoaded               | Function checking if the history is loaded                                                                                                                                                                                                                                                |
 | resetInProgressAggregatedData | Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.enedis.year : `{ load: 76.712, year: 2020, ... }` need to be replace by `{ load: 82.212, year: 2020, ... }` after enedis data reprocess |
 
diff --git a/docs/konnectors/grdf.md b/docs/konnectors/grdf.md
index 647d04e03482aa7a510f59e3f0d69c3f5ce21c60..ac82396d20a0710277207eb6afa1a092efcd34fd 100644
--- a/docs/konnectors/grdf.md
+++ b/docs/konnectors/grdf.md
@@ -1,4 +1,4 @@
-This konnector fetches consumptions measures from Grdf Adict API. This is an Oauth Konnector, meaning the authentification performed to access all data is made following an Oauth2 protocol.
+This konnector fetches consumptions measures from Grdf Adict API. This is an Oauth Konnector, meaning the authentication performed to access all data is made following an Oauth2 protocol.
 You can clone the project [here](https://forge.grandlyon.com/web-et-numerique/llle_project/grdf-adict-konnector).
 
 You should also check Cozy's official documentations for konnectors :
@@ -13,7 +13,7 @@ All the actions performed by the stack are targetted from pre-registered paramat
 
 ![grdfgrandlyon account](/img/grdf_account.jpg)
 
-On its first launch, following the Oauth Client Connect authentification.
+On its first launch, following the Oauth Client Connect authentication.
 
 - The cozy stack calls the **authentification_endpoint** and start the oauth protocol, see [proxy doc](/proxy/description).
 - The account has now an access_token and an id_token from the oauth call
@@ -81,6 +81,6 @@ Build branch is stored as a docker image in a registry : [Container Registry](ht
 | processData                   | Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data                                                                                                                                                             |
 | storeData                     | Save data in the right doctype db and prevent duplicated keys                                                                                                                                                                                                                         |
 | formateData                   | Format data for DB storage and remove bad data                                                                                                                                                                                                                                        |
-| buildAgregatedData            | Retrieve and remove old data for a specific doctype and return an array of agregated data                                                                                                                                                                                             |
+| buildAggregatedData            | Retrieve and remove old data for a specific doctype and return an array of aggregated data                                                                                                                                                                                             |
 | buildDataFromKey              | Format an entry for DB storage using key and value. For year doctype: key = "YYYY". For month doctype: key = "YYYY-MM"                                                                                                                                                                |
 | resetInProgressAggregatedData | Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.grdf.year : `{ load: 76.712, year: 2020, ... }` need to be replace by `{ load: 82.212, year: 2020, ... }` after grdf data reprocess |
diff --git a/docs/pilote/Pilote - TS - Back/functionalities/routes.md b/docs/pilote/Pilote - TS - Back/functionalities/routes.md
index 31019e4e435719b0198c28bff55acc8022fc8a38..7aa87399ceeba02f01dc3a000c189910bc3bc6ed 100644
--- a/docs/pilote/Pilote - TS - Back/functionalities/routes.md	
+++ b/docs/pilote/Pilote - TS - Back/functionalities/routes.md	
@@ -4,7 +4,7 @@ A swagger documentation can be consulted at [http://localhost:3000/api/doc/](htt
 
 # Auth
 
-- `api/auth/signin`: It is used for local and dev authentification. It is linked to two different password into the database.
+- `api/auth/signin`: It is used for local and dev authentication. It is linked to two different password into the database.
 
 - `api/auth/token` : It is used for generate one token. Only for internal process. This route is not call from another apps.
 
@@ -12,9 +12,9 @@ A swagger documentation can be consulted at [http://localhost:3000/api/doc/](htt
 
 - `api/auth/token`: It is used for generate one token. Only for internal process. This route is not call from another apps.
 
-- `api/auth/login`: It is used for Sign&Go authentification. Linked to AuthStrategy.
+- `api/auth/login`: It is used for Sign&Go authentication. Linked to AuthStrategy.
 
-- `login/callback`: Get the authentification from Sign&Go process.
+- `login/callback`: Get the authentication from Sign&Go process.
 
 
 # Beneficiary
@@ -43,5 +43,5 @@ A swagger documentation can be consulted at [http://localhost:3000/api/doc/](htt
 
 # Users
 
-Authentification only used for local or dev environment because Sign&Go is only available for rec and prod env. 
+Authentication only used for local or dev environment because Sign&Go is only available for rec and prod env. 
 
diff --git a/docs/pilote/Pilote - TS - Back/getting_started/launch_local_application.md b/docs/pilote/Pilote - TS - Back/getting_started/launch_local_application.md
index 1e36cfb9815718cc10e2581555d9d249bf52f1b6..1de15b0a7921d9c804e41e40c06bd2e1a2ba02f8 100644
--- a/docs/pilote/Pilote - TS - Back/getting_started/launch_local_application.md	
+++ b/docs/pilote/Pilote - TS - Back/getting_started/launch_local_application.md	
@@ -12,7 +12,7 @@ git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travaille
 
 ### Start Pilote application
 
-To start Pilote application just launch the command in a PowerShell or Windows Powershell tool:
+To start Pilote application just launch the command in a Powershell or Windows Powershell tool:
 
 ```
 yarn docker:dev
@@ -32,7 +32,7 @@ It will be redirect to the Swagger UI. It allow to test the different API define
 
 ### Run Jest test 
 
-To start test defined just run the command in a PowerShell or Windows Powershell tool:
+To start test defined just run the command in a Powershell or Windows Powershell tool:
 
 ```
 yarn test:watch
@@ -41,17 +41,17 @@ yarn test:watch
 Don't forget to uncomment ending row into beneficiary.service.ts file before to run the above command.
 
 
-### Usefull docker command
+### Useful docker command
 
 - build : `docker build -t mps .`
 
 - run container : `docker-compose -f docker-compose.yml up --remove-orphans`
 
-- acceder à la db du container: `docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres`
+- access container db: `docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres`
 
 - delete image/containers: `docker system prune -a -f`
 
-- voir le contenu du container:	`docker exec -it <id_container> bash`
+- enter container:	`docker exec -it <id_container> bash`
 
 - remove container: `docker container rm -f <id_container>`
 
diff --git a/docs/pilote/Pilote - TS - Back/getting_started/setup_your_environment.md b/docs/pilote/Pilote - TS - Back/getting_started/setup_your_environment.md
index f8e6d09b48fb8c39c01a0923dfde5cecceeeadfa..d93694806429ce79160f6536ea1c482ebe863580 100644
--- a/docs/pilote/Pilote - TS - Back/getting_started/setup_your_environment.md	
+++ b/docs/pilote/Pilote - TS - Back/getting_started/setup_your_environment.md	
@@ -45,7 +45,7 @@ Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
 
 ## Yarn
 
-Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager.
+Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager.
 Installation for yarn can be found here: [Installation of Yarn](https://classic.yarnpkg.com/fr/docs/install/).
 
 ## Docker
diff --git a/docs/pilote/Pilote - TS - Front/functionalities/functions.md b/docs/pilote/Pilote - TS - Front/functionalities/functions.md
index 1e85d43197f4e929e638211c83475b9b2169c85b..c3dc47fb6525881d4618c7a7c06af9fd1873a559 100644
--- a/docs/pilote/Pilote - TS - Front/functionalities/functions.md	
+++ b/docs/pilote/Pilote - TS - Front/functionalities/functions.md	
@@ -1,6 +1,6 @@
-This section explains the different functionalitites :
+This section explains the different functionalities:
 
-# Beneficiairies 
+# Beneficiaries 
 
 Once you are authenticated, you'll redirect into /liste-beneficiaire route.
 
diff --git a/docs/pilote/Pilote - TS - Front/getting_started/launch_local_application.md b/docs/pilote/Pilote - TS - Front/getting_started/launch_local_application.md
index d33ec25c8db297353010a76b27e2154acc042e0e..3b9db5ba4c6365cfae485214f8cbb54ede343d05 100644
--- a/docs/pilote/Pilote - TS - Front/getting_started/launch_local_application.md	
+++ b/docs/pilote/Pilote - TS - Front/getting_started/launch_local_application.md	
@@ -18,7 +18,7 @@ Before to start Pilote application, you need to run this command in order to ins
 yarn install
 ```
 
-To start Pilote application just launch the command in a PowerShell or Windows Powershell tool:
+To start Pilote application just launch the command in a Powershell or Windows Powershell tool:
 
 ```
 yarn start
diff --git a/docs/pilote/Pilote - Usager/application/deploy.md b/docs/pilote/Pilote - Usager/application/deploy.md
index 72a872cc3e8636474c2598018d95eadd08fcc351..33be66e3eab35bfd144da7ce5cc132cd6b7c4107 100644
--- a/docs/pilote/Pilote - Usager/application/deploy.md	
+++ b/docs/pilote/Pilote - Usager/application/deploy.md	
@@ -19,7 +19,7 @@ This command will install WSL on your computer. After this, you'll need to **reb
 
 ### Install your Linux distribution
 
-After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 LTS). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.
+After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 lts). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.
 
 To make sure it's correctly installed and working, you can open Powershell and paste the following command : 
 
@@ -55,7 +55,7 @@ To verify the npm Install check using the command :
 ```
 npm --version
 ```
-To Downlaod and Setup Yarn
+To Download and Setup Yarn
 ```
 sudo apt install yarn
 ```
diff --git a/docs/pilote/Pilote - Usager/application/scaffolding.md b/docs/pilote/Pilote - Usager/application/scaffolding.md
index f404322e0cb2975084e77964b9b9bda8de489fa1..464221051a9895fb7d191d1dfcf314ad1e194a8a 100644
--- a/docs/pilote/Pilote - Usager/application/scaffolding.md	
+++ b/docs/pilote/Pilote - Usager/application/scaffolding.md	
@@ -30,7 +30,7 @@ In this section, you will find information about the project file structure and
 | app.config.*              | Overloads webpack configuration                              |
 | jest.config.js            | Jest config file                                             |
 | manifest.webapp           | Manifest of the application, used by cozy for permissions' management. You can add permissions for doctypes here |
-| tsconfig.json             | TypeScript config file                                       |
+| tsconfig.json             | Typescript config file                                       |
 | konnector-dev-config.json | To locally test konnectors                                   |
 | service-dev-config.json   | To locally test services                                     |
 
diff --git a/docs/pilote/Pilote - Usager/application/services.md b/docs/pilote/Pilote - Usager/application/services.md
index 1438712c90c4cc553fe4c3fdda5e6eccea3703bf..79bec2d819c3cd3a0203a4f6440e2961267d9fb6 100644
--- a/docs/pilote/Pilote - Usager/application/services.md	
+++ b/docs/pilote/Pilote - Usager/application/services.md	
@@ -25,7 +25,7 @@
 
 ### Functions
 
-- `parseAppointment`: Returns an Appointment from an AppointmentEntity.
+- `parseAppointment`: Returns an Appointment from an appointmentEntity.
 - `getLastAppointment`: Returns the last Appointment, which a user can see first in /actions.
 - `getAllAppointment`: returns a list of all Appointments.
 - `getAppointmentByID`: Returns an Appointment from its id.
@@ -93,7 +93,7 @@
 - `getKonnectorNameBySlug`: Returns a Konnector name from a slug.
 - `getKonnectorBySlug`: Returns a Konnector from a slug.
 - `getKonnectorByName`: Returns a Konnector from its name.
-- `getKonnectorsFromDocuments`: Returns a list of Konnectors from a passed DocumentEntity list.
+- `getKonnectorsFromDocuments`: Returns a list of Konnectors from a passed documentEntity list.
 
 
 
@@ -136,4 +136,4 @@
 
 ### Functions
 
-- `getAllTriggers`: Returns All the triggers filtred by type if passed as parameter.
\ No newline at end of file
+- `getAllTriggers`: Returns All the triggers filtered by type if passed as parameter.
\ No newline at end of file
diff --git a/docs/pilote/Pilote - Usager/functionalities/appointments.md b/docs/pilote/Pilote - Usager/functionalities/appointments.md
index 19b7d0ae4bce4f3f511174746c2f6cf7550937a7..ad99d4f903dc9fd55c42437c6364c4a8b2aedcdf 100644
--- a/docs/pilote/Pilote - Usager/functionalities/appointments.md	
+++ b/docs/pilote/Pilote - Usager/functionalities/appointments.md	
@@ -1 +1 @@
-This section explain all the functionnalities in the appointment part
+This section explain all the functionalities in the appointment part
diff --git a/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md b/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md
index 6c870190b6dec2e6e6e968fe8731f371ebeb8595..5f9c9d1ba403e489e6df70a6614a72c2a87e2c33 100644
--- a/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md	
+++ b/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md	
@@ -1,5 +1,5 @@
 ## Use cozy-doctype in local
-In order to be able to use our own cozy-doctype, especialy remote doctype here, we need to use them in local.
+In order to be able to use our own cozy-doctype, especially remote doctype here, we need to use them in local.
 
 1/ clone [cozy-doctypes](https://github.com/cozy/cozy-doctypes) repository into your system.
 Then, push it into your root project.
@@ -28,7 +28,7 @@ cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype
 cozy-stack serve (...) --doctypes /data/cozy-doctypes
 ```
 !!! warning "warning"
-    You need to build and push the newlest image on the forge registry when the step 3 is done.
+    You need to build and push the newest image on the forge registry when the step 3 is done.
     You must have all files, into your docker folder, in LF mode of  "End of Line Sequence" !
 
 For this project:
diff --git a/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md b/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md
index 092c4ab8578f059980deb431e65fcec6b40b0138..76462edb38c829666cbd25e7c7bf81654008d814 100644
--- a/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md	
+++ b/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md	
@@ -66,10 +66,10 @@ konnectors:
 
 
 !!! warning "warning"
-    You need to build and push the newlest image on the forge registry when the step 6 is done.
+    You need to build and push the newest image on the forge registry when the step 6 is done.
     You must have all files, into your docker folder, in LF mode of  "End of Line Sequence" !
 
-Finaly, you should rebuild the docker image of the cozy-stack:
+Finally, you should rebuild the docker image of the cozy-stack:
 ```
 cd docker
 docker build .
diff --git a/docs/pilote/index.md b/docs/pilote/index.md
index f664267e33dbcc78f6a4a9f12b3e32ac581746eb..9d07c190a102b98636533080792589b4f196357c 100644
--- a/docs/pilote/index.md
+++ b/docs/pilote/index.md
@@ -1,6 +1,6 @@
 ![pilote](../../img/mps.png){: .center}
 
-Pilote aims to help people in various administrative processes, allowing them to share their personnal informations with a social worker to build the best possible claim for every needs.
+Pilote aims to help people in various administrative processes, allowing them to share their personal information with a social worker to build the best possible claim for every needs.
 
 
 !!! danger "Reminder"
diff --git a/docs/proxy/description.md b/docs/proxy/description.md
index b12dc5fa09821d7c8446a4056d20aacc52b58d66..6d4cf35957077293c7197dfde53263127c1c0c5b 100644
--- a/docs/proxy/description.md
+++ b/docs/proxy/description.md
@@ -18,9 +18,9 @@ See both **[Enedis](./use_cases/enedis.md)** and **[Grdf](./use_cases/grdfadict.
 
 #### Couchdb
 
-The couchdb database must hold all informations needed for the konnector authentication to work properly.
+The couchdb database must hold all information needed for the konnector authentication to work properly.
 
-Auth informations are stored in the **secrets/io-cozy-account_types** database.
+Auth information are stored in the **secrets/io-cozy-account_types** database.
 You can create manually the document by entering these parameters for each konnector:
 
 <table>
@@ -70,11 +70,11 @@ Once the document is created, when launching the konnector from the cozy-home or
 
 The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step.
 
-If the token request is a success. An account/service-name database will be added in couchdb containing all informations needed for authentication and the konnector will be free to work on all endpoints within its scope.
+If the token request is a success. An account/service-name database will be added in couchdb containing all information needed for authentication and the konnector will be free to work on all endpoints within its scope.
 
 ### Why we Need a Proxy
 
-The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personnal clouds, following this guideline would mean that we need a **client_id** and a **client_secret** for each one of all the applications running.
+The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personal clouds, following this guideline would mean that we need a **client_id** and a **client_secret** for each one of all the applications running.
 
 To answer this issue, two solutions are possible depending on what the energy supplier is willing to do.
 
@@ -87,7 +87,7 @@ Example:
     xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz
     toto.cozygrandlyon.cloud/account/redirect -> redirect to toto
 
-- If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirections. 
+- If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirection. 
 
 #### Result
 
@@ -124,7 +124,7 @@ It is composed of six endpoints as seen above. The first endpoint to be called i
 
 #### auth
 
-Originally called from a cozy-stack trying to setup its konnector. The proxy gets these informations from the query:
+Originally called from a cozy-stack trying to setup its konnector. The proxy gets these information from the query:
 
 - client_id
 - duration
@@ -136,12 +136,12 @@ Originally called from a cozy-stack trying to setup its konnector. The proxy get
 
 The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling.
 
-With all these informations, the proxy can contact the provider **/auth** endpoint to start the oauth dance.
+With all these information, the proxy can contact the provider **/auth** endpoint to start the oauth dance.
 
 ##### Enedis
 
 !!! warning "note"
-    See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the cozyOrigin instance name. This will be usefull when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer.
+    See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the original instance name. This will be useful when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer.
 
 Once the call is sent, enedis will point to the **/redirect** endpoint.
 
diff --git a/docs/proxy/use_cases/enedis.md b/docs/proxy/use_cases/enedis.md
index 4ea649c23033431d38d89136d4b638d1e12cef59..59ac64140d3046661a33488be9505e37e0ebe1ff 100644
--- a/docs/proxy/use_cases/enedis.md
+++ b/docs/proxy/use_cases/enedis.md
@@ -92,7 +92,7 @@ Regarding Enedis, two endpoints are exposed:
   </tbody>
 </table>
 
-On success, response will contain **access_token** or **refresh_token**, **usage_point_id** among other things. All informations will be stored by the cozy-stack in a cozy-accounts database.
+On success, response will contain **access_token** or **refresh_token**, **usage_point_id** among other things. All information will be stored by the cozy-stack in a cozy-accounts database.
 
 #### Consent Handling
 
diff --git a/docs/proxy/use_cases/grdfadict.md b/docs/proxy/use_cases/grdfadict.md
index f11db6028575456bcff1d548b39c8565fb8d9cdc..a0e35353d8445ef59cc51057703f6b56f4578ac0 100644
--- a/docs/proxy/use_cases/grdfadict.md
+++ b/docs/proxy/use_cases/grdfadict.md
@@ -4,9 +4,9 @@
     Visit [https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict](https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict) to explore all the services exposed by Grdf.
     > Prod endpoints are: [https://sofit-sso-oidc.grdf.fr/openam/](https://sofit-sso-oidc.grdf.fr/openam/)
 
-Regarding Grdf Adict Oauth connexion, two endpoints are exposed:
+Regarding Grdf Adict Oauth connection, two endpoints are exposed:
 
-!!! warning "Oauth connexion still in Beta"
+!!! warning "Oauth connection still in Beta"
     Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a *state* parameter in the Oauth dance.
 
 #### Authorize
diff --git a/docs/src/dictionary/en-custom.txt b/docs/src/dictionary/en-custom.txt
index 3cede9a160962d2fa5c8c4f5e0c6e9259bd2532d..c12f10d8777a4f733e74330747028a9c88e21ad5 100644
--- a/docs/src/dictionary/en-custom.txt
+++ b/docs/src/dictionary/en-custom.txt
@@ -1,8 +1,18 @@
 ACH
 Adict
+API
+APIs
 Api
+Apis
 Arg
 Args
+Boolean
+Config
+Cron
+CGU
+CSS
+DOM
+DocumentEntity
 Ecolyo
 Ecogesture
 Ecogestures
@@ -10,69 +20,194 @@ Eau
 Egl
 ESLint
 Dacc
+Datahub
 Dev
 DEV
+Du
 Dockerfile
+Init
+Icescrum
 Grafana
 Gitflow
+Gitlab
 GLIBC
 Grandlyon
-Usager
+GIF
+GIFs
+Gif
+Halfhour
 Konnector
 Konnectors
+Lyon
 MobaXterm
-Mkdocs
+MaxPower
 MkDocs
+Mjml
+NestJs
 Oauth
+OAuth
 Pilote
+Usager
+PNGs
+PNG
+Powershell
+Ressources
 SMS
+SVG
+SVGs
+TaskItem
+TaskItems
 Typescript
+Ui
+UI
+YYYY
+WSL
+WSDL
+VSCode
+VScode
+Vscode
 acces
 adict
+addData
 api
 auth
+aggregateHourlyData
+aggregateMonthAndYearData
+appDirectory
+appointmentEntity
+backend
+beneficiaire
+boolean
+buildAggregatedData
+buildDataFromKey
+cmd
+cmds
+css
 couchdb
+conf
+config
+ci
+challengeActionNotification
+challengeDuelNotification
+challengeExplorationNotification
+connectionDate
+currentChallenge
+currentDatachart
+currentDatachartIndex
+currentDataload
+currentIndex
+currentTimeStep
+customed
+dataconnect
+documentEntity
 debian
 doctype
 doctypes
 droit
+du
+easycozy
 ecolyo
 ecolyotest
 ecogesture
 ecogestures
+editorconfig
+eslintrc
 egl
+eglgrandlyon
 enedis
 enedisgrandlyon
+env
 externeGrdf
 cozysessid
+datahub
 dev
+dom
+frontend
+formateData
+getDailyData
+getLoadData
+getMaxPower
 gitlab
 grafana
 grandlyon
 grdf
+grdfgrandlyon
 golang
 healthcheck
+hotWater
+http
+https
+hydrateAndFilter
+io
+isHistoryLoaded
+javascript
 js
 json
+kVA
+kW
 konnector
 konnectors
+launchLoadDataProcess
+lts
 loki
+lottie
+lyon
 liste
 linux
 libc
+maxpower
+multifluid
+mps
 microsoft
+middleware
+mixins
+mixin
+npm
+nodejs
 ubuntu
+uml
 uri
 url
+utils
 userChallenge
+usager
+usagers
 oauth
 params
 pilote
+processData
+profileType
+powershell
+prettierrc
 png
 scaleway
+sendmail
 sharecode
+showConsentModal
 smtp
+sms
+src
 rabbitmq
+runtime
 reactjs
+resetInProgressAggregatedData
 redux
-webapp
\ No newline at end of file
+startLoadDataProcess
+storeData
+swipeable
+stylesheet
+travailleur
+timestep
+tsx
+tsconfig
+viewedInSelection
+vscode
+webapp
+webhook
+webhooks
+webservice
+webpack
+weekDaysHalfHourAverageValues
+wsl
+yaml
+yml
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index 218865fd873b1b766274433d3c760cf8abd2a0c0..78404ed2d4314dc1a47439d8747a6a25d88f3aa8 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -6,7 +6,7 @@ repo_url: "https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-t
 
 theme:
   name: "material"
-  logo: 'img/self_data_grdlyon.png'
+  logo: "img/self_data_grdlyon.png"
   favicon: "img/self_data_grdlyon.png"
   palette:
     scheme: dracula
@@ -33,15 +33,13 @@ markdown_extensions:
   - pymdownx.tabbed:
       alternate_style: true
 
-
-
 extra_css:
   - "stylesheets/extra.css"
 
 plugins:
   - search
   - git-revision-date-localized
-      
+
 nav:
   - Home:
       - Getting started: index.md
@@ -62,8 +60,8 @@ nav:
           - Architecture: ecolyo/project_architecture/architecture.md
           - Libraries: ecolyo/project_architecture/libraries.md
           - Environments: ecolyo/project_architecture/environments.md
-          - DocTypes: ecolyo/project_architecture/doctypes.md
-          - Remote DocTypes: ecolyo/project_architecture/remote_doctypes.md
+          - Doctypes: ecolyo/project_architecture/doctypes.md
+          - Remote Doctypes: ecolyo/project_architecture/remote_doctypes.md
       - Application:
           - Deploy: ecolyo/application/deploy.md
           - Description: ecolyo/application/description.md
@@ -99,7 +97,7 @@ nav:
               - Libraries: ecolyo/ecolyo-agent/getting_started/libraries.md
           - Functionalities:
               - General: ecolyo/ecolyo-agent/functionalities/general.md
-              - Authentification: ecolyo/ecolyo-agent/functionalities/authentification.md
+              - Authentication: ecolyo/ecolyo-agent/functionalities/authentication.md
               - Routes: ecolyo/ecolyo-agent/functionalities/routes.md
           - Development:
               - Deploy: ecolyo/ecolyo-agent/development/deploy.md
@@ -144,6 +142,7 @@ nav:
   - Konnectors:
       - Introduction: konnectors/index.md
       - Enedis: konnectors/enedis.md
+      - Enedis SGE: konnectors/enedis-sge.md
       - GRDF: konnectors/grdf.md
       - Eau du Grand Lyon: konnectors/egl.md
   - Proxy:
diff --git a/site/404.html b/site/404.html
index f48d025e77bf0a748f8e55b78ce8a2e6fc2c43d8..3d9cdf9c16e178e3e71ed0741e4b981a648d9dba 100644
--- a/site/404.html
+++ b/site/404.html
@@ -662,7 +662,7 @@
   
     <li class="md-nav__item">
       <a href="/ecolyo/project_architecture/doctypes/" class="md-nav__link">
-        DocTypes
+        Doctypes
       </a>
     </li>
   
@@ -676,7 +676,7 @@
   
     <li class="md-nav__item">
       <a href="/ecolyo/project_architecture/remote_doctypes/" class="md-nav__link">
-        Remote DocTypes
+        Remote Doctypes
       </a>
     </li>
   
@@ -1286,8 +1286,8 @@
   
   
     <li class="md-nav__item">
-      <a href="/ecolyo/ecolyo-agent/functionalities/authentification/" class="md-nav__link">
-        Authentification
+      <a href="/ecolyo/ecolyo-agent/functionalities/authentication/" class="md-nav__link">
+        Authentication
       </a>
     </li>
   
diff --git a/site/index.html b/site/index.html
index eaece81713f6454d8b894debd3226af96f769ace..5b64641c8d78cdd23b09e319d3c49c79e75b9838 100644
--- a/site/index.html
+++ b/site/index.html
@@ -773,7 +773,7 @@
   
     <li class="md-nav__item">
       <a href="ecolyo/project_architecture/doctypes/" class="md-nav__link">
-        DocTypes
+        Doctypes
       </a>
     </li>
   
@@ -787,7 +787,7 @@
   
     <li class="md-nav__item">
       <a href="ecolyo/project_architecture/remote_doctypes/" class="md-nav__link">
-        Remote DocTypes
+        Remote Doctypes
       </a>
     </li>
   
@@ -1397,8 +1397,8 @@
   
   
     <li class="md-nav__item">
-      <a href="ecolyo/ecolyo-agent/functionalities/authentification/" class="md-nav__link">
-        Authentification
+      <a href="ecolyo/ecolyo-agent/functionalities/authentication/" class="md-nav__link">
+        Authentication
       </a>
     </li>
   
@@ -2614,7 +2614,7 @@
 <tr>
 <td><a href="https://www.docker.com/get-started">Docker</a></td>
 <td>Yes</td>
-<td>See <a href="">cozystack</a> for more informations.</td>
+<td>See <a href="">cozystack</a> for more information.</td>
 </tr>
 <tr>
 <td><a href="https://docs.docker.com/compose/install/">Docker-compose</a></td>
@@ -2684,7 +2684,7 @@ For information please visit <a href="https://aka.ms/wsl2kernel">wsl2kernel</a>.
 </div>
 <p>If you install the MSI from <a href="https://aka.ms/wsl2kernel">wsl2kernel</a>. Once you have the kernel installed, please run <code>wsl --set-default-version 2</code> again and it should complete successfully without showing the message.</p>
 <h4 id="install-your-linux-distribution">Install your Linux distribution</h4>
-<p>After reboot, open the microsoft store and install the distribution of your choice, for instance: <mark>Ubuntu 20.04 LTS</mark>. Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.</p>
+<p>After reboot, open the microsoft store and install the distribution of your choice, for instance: <mark>Ubuntu 20.04 lts</mark>. Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account.</p>
 <p>To make sure it's correctly installed and working, you can open Powershell and paste the following command :</p>
 <div class="highlight"><pre><span></span><code><span class="n">wsl</span><span class="p">.</span><span class="n">exe</span> <span class="p">-</span><span class="n">-list</span> <span class="p">-</span><span class="n">-running</span>
 </code></pre></div>
@@ -2717,7 +2717,7 @@ For information please visit <a href="https://aka.ms/wsl2kernel">wsl2kernel</a>.
 </code></pre></div></p>
 </li>
 <li>
-<p>To Downlaod and Setup Yarn
+<p>To Download and Setup Yarn
     <div class="highlight"><pre><span></span><code><span class="gp">$ </span>sudo apt install yarn
 </code></pre></div></p>
 </li>
@@ -2753,7 +2753,7 @@ source ~/.bashrc
   <small>
     
       Last update:
-      <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">April 26, 2022</span>
+      <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">April 28, 2022</span>
       
     
   </small>
diff --git a/site/search/search_index.json b/site/search/search_index.json
index 7744583d0db68927a58c070276138a6ea9e7e925..e68b729d496a859aa1cc9cfcfeb7c56349be23a7 100644
--- a/site/search/search_index.json
+++ b/site/search/search_index.json
@@ -1 +1 @@
-{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"This documentation covers the technical aspects of projects developed by the Grandlyon in cooperation with Cozy Cloud . Installing prerequisites In order to work with a self-data environment, there are a couple of prerequisites. Don't forget to take a look at our general development guidelines wiki first. Name Required Details Node Yes Node 16 must be installed as it is the version that runs on the official cozystack. Yarn Yes Yarn is our projects package manager. Docker Yes See cozystack for more informations. Docker-compose Yes WSL No Required for windows users. Usage Node NVM You might need to manage several NodeJS versions on the same computer when working on different projects. To manage it properly, you can use the nvm package on windows or n package on linux. $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version $ nvm install X.X.X $ nvm list $ nvm use X.X.X $ node -v WSL First open Powershell as administrator and launch the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot . Upgrade to WSL 2 If you're on WSL 1 and want to upgrade to WSL 2, here is the process: Open an elevated powershell and paste the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart Then, enable the Virtual Machine Platform optional feature. dism . exe / online / enable-feature / featurename : VirtualMachinePlatform / all / norestart Now restart your computer to apply these features. Once it's done, open an elevated powershell again and set the default wsl version to 2 $ wsl --set-default-version 2 You might see this message after running the command above WSL 2 requires an update to its kernel component. For information please visit wsl2kernel . If you install the MSI from wsl2kernel . Once you have the kernel installed, please run wsl --set-default-version 2 again and it should complete successfully without showing the message. Install your Linux distribution After reboot, open the microsoft store and install the distribution of your choice, for instance: Ubuntu 20.04 LTS . Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list. Setup your distribution Start updating the packages list by typing: $ sudo apt update Install nodejs using the apt package manager $ sudo apt install To verify the Installation execute the following command: $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: $ sudo apt install npm To verify the npm Install check using the command: $ npm --version To Downlaod and Setup Yarn $ sudo apt install yarn To check the installed version of Yarn: $ yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands: sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on. Contributing to the documentation To install and run the documentation on your laptop, follow the steps in the README . Then: Create a branch for your change Add documentation pages to docs , and supporting assets to img . Write some markdown Submit a merge request","title":"Getting started"},{"location":"#_1","text":"This documentation covers the technical aspects of projects developed by the Grandlyon in cooperation with Cozy Cloud .","title":""},{"location":"#installing-prerequisites","text":"In order to work with a self-data environment, there are a couple of prerequisites. Don't forget to take a look at our general development guidelines wiki first. Name Required Details Node Yes Node 16 must be installed as it is the version that runs on the official cozystack. Yarn Yes Yarn is our projects package manager. Docker Yes See cozystack for more informations. Docker-compose Yes WSL No Required for windows users.","title":"Installing prerequisites"},{"location":"#usage","text":"","title":"Usage"},{"location":"#node-nvm","text":"You might need to manage several NodeJS versions on the same computer when working on different projects. To manage it properly, you can use the nvm package on windows or n package on linux. $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version $ nvm install X.X.X $ nvm list $ nvm use X.X.X $ node -v","title":"Node NVM"},{"location":"#wsl","text":"First open Powershell as administrator and launch the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot .","title":"WSL"},{"location":"#upgrade-to-wsl-2","text":"If you're on WSL 1 and want to upgrade to WSL 2, here is the process: Open an elevated powershell and paste the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart Then, enable the Virtual Machine Platform optional feature. dism . exe / online / enable-feature / featurename : VirtualMachinePlatform / all / norestart Now restart your computer to apply these features. Once it's done, open an elevated powershell again and set the default wsl version to 2 $ wsl --set-default-version 2 You might see this message after running the command above WSL 2 requires an update to its kernel component. For information please visit wsl2kernel . If you install the MSI from wsl2kernel . Once you have the kernel installed, please run wsl --set-default-version 2 again and it should complete successfully without showing the message.","title":"Upgrade to WSL 2"},{"location":"#install-your-linux-distribution","text":"After reboot, open the microsoft store and install the distribution of your choice, for instance: Ubuntu 20.04 LTS . Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list.","title":"Install your Linux distribution"},{"location":"#setup-your-distribution","text":"Start updating the packages list by typing: $ sudo apt update Install nodejs using the apt package manager $ sudo apt install To verify the Installation execute the following command: $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: $ sudo apt install npm To verify the npm Install check using the command: $ npm --version To Downlaod and Setup Yarn $ sudo apt install yarn To check the installed version of Yarn: $ yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands: sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on.","title":"Setup your distribution"},{"location":"#contributing-to-the-documentation","text":"To install and run the documentation on your laptop, follow the steps in the README . Then: Create a branch for your change Add documentation pages to docs , and supporting assets to img . Write some markdown Submit a merge request","title":"Contributing to the documentation"},{"location":"external_doc/","text":"Grandlyon ressources Link Details WIKI This wiki covers all the processes and guidelines towards developers. Cozy ressources Link Details COZY Full technical documentation for all cozy libs. MATTERMOST Chat app for exange between G.Lyon & Cozy.","title":"Additional Ressources"},{"location":"external_doc/#grandlyon-ressources","text":"Link Details WIKI This wiki covers all the processes and guidelines towards developers.","title":"Grandlyon ressources"},{"location":"external_doc/#cozy-ressources","text":"Link Details COZY Full technical documentation for all cozy libs. MATTERMOST Chat app for exange between G.Lyon & Cozy.","title":"Cozy ressources"},{"location":"easycozy/","text":"What is easy-cozy Why we use easy-cozy How we use it","title":"Introduction"},{"location":"easycozy/#what-is-easy-cozy","text":"","title":"What is easy-cozy"},{"location":"easycozy/#why-we-use-easy-cozy","text":"","title":"Why we use easy-cozy"},{"location":"easycozy/#how-we-use-it","text":"","title":"How we use it"},{"location":"easycozy/commands/","text":"Commands This section includes all common commands used on dev environment. App Install a specific version of an app $ cd /easy-cozy $ docker-compose exec cozy ./cozy apps update home --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://github.com/doubleface/cozy-collect.git#build-debug Konnector Install a specific version of a konnector $ cd /easy-cozy # cozy-stack konnectors uninstall ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors uninstall grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been uninstalled # cozy-stack konnectors install ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors install grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://forge.grandlyon.com/web-et-numerique/llle_project/grdf-adict-konnector.git#build grdfgrandlyon ( 0 .1.5-a3f6f05d9fde7c705b811658b3ce3667a9d7d0b5 ) has been installed on [ name ] .cozy.self-data.alpha.grandlyon.com Update the version of a konnector $ cd /easy-cozy # cozy-stack konnectors update ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors update grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been upgraded to 0 .1.5-d4bbe7350ecf13d13734f559c538e3c0ee8dc7ae Run a konnector from the stack $ cd /root/easy-cozy # cozy-stack konnectors run ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors run grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" Instance Set log level to debug for an instance $ cd /root/easy-cozy # cozy-stack instances debug ${url} true $ docker-compose exec cozy ./cozy instances debug --domain \"[name].cozy.self-data.alpha.grandlyon.com\" true List all instances $ cd /root/easy-cozy # cozy-stack instances ls $ docker-compose exec cozy ./cozy instances ls Stack Check stack version $ cd /easy-cozy $ docker-compose exec cozy ./cozy version Update stack version Update version in the Dockerfile on gitlab. On server : git pull or change locally the version in cozy-stack/Dockerfile create the docker image using: cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image cd .. docker-compose up -d cozy Error encounter Docker container was not launched, when consulting logs we can see the following error ./cozy: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./cozy) We have replaced debian:stable-slim with ubuntu:20.10 as installer for our docker build: https://forge.grandlyon.com/pocs/cozy/easy-cozy/-/commit/48a30a03f209169e0f1ebb0d106bb4361e7cd167","title":"Commands"},{"location":"easycozy/commands/#commands","text":"This section includes all common commands used on dev environment.","title":"Commands"},{"location":"easycozy/commands/#app","text":"","title":"App"},{"location":"easycozy/commands/#install-a-specific-version-of-an-app","text":"$ cd /easy-cozy $ docker-compose exec cozy ./cozy apps update home --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://github.com/doubleface/cozy-collect.git#build-debug","title":"Install a specific version of an app"},{"location":"easycozy/commands/#konnector","text":"","title":"Konnector"},{"location":"easycozy/commands/#install-a-specific-version-of-a-konnector","text":"$ cd /easy-cozy # cozy-stack konnectors uninstall ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors uninstall grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been uninstalled # cozy-stack konnectors install ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors install grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://forge.grandlyon.com/web-et-numerique/llle_project/grdf-adict-konnector.git#build grdfgrandlyon ( 0 .1.5-a3f6f05d9fde7c705b811658b3ce3667a9d7d0b5 ) has been installed on [ name ] .cozy.self-data.alpha.grandlyon.com","title":"Install a specific version of a konnector"},{"location":"easycozy/commands/#update-the-version-of-a-konnector","text":"$ cd /easy-cozy # cozy-stack konnectors update ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors update grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been upgraded to 0 .1.5-d4bbe7350ecf13d13734f559c538e3c0ee8dc7ae","title":"Update the version of a konnector"},{"location":"easycozy/commands/#run-a-konnector-from-the-stack","text":"$ cd /root/easy-cozy # cozy-stack konnectors run ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors run grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\"","title":"Run a konnector from the stack"},{"location":"easycozy/commands/#instance","text":"","title":"Instance"},{"location":"easycozy/commands/#set-log-level-to-debug-for-an-instance","text":"$ cd /root/easy-cozy # cozy-stack instances debug ${url} true $ docker-compose exec cozy ./cozy instances debug --domain \"[name].cozy.self-data.alpha.grandlyon.com\" true","title":"Set log level to debug for an instance"},{"location":"easycozy/commands/#list-all-instances","text":"$ cd /root/easy-cozy # cozy-stack instances ls $ docker-compose exec cozy ./cozy instances ls","title":"List all instances"},{"location":"easycozy/commands/#stack","text":"","title":"Stack"},{"location":"easycozy/commands/#check-stack-version","text":"$ cd /easy-cozy $ docker-compose exec cozy ./cozy version","title":"Check stack version"},{"location":"easycozy/commands/#update-stack-version","text":"Update version in the Dockerfile on gitlab. On server : git pull or change locally the version in cozy-stack/Dockerfile create the docker image using: cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image cd .. docker-compose up -d cozy Error encounter Docker container was not launched, when consulting logs we can see the following error ./cozy: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./cozy) We have replaced debian:stable-slim with ubuntu:20.10 as installer for our docker build: https://forge.grandlyon.com/pocs/cozy/easy-cozy/-/commit/48a30a03f209169e0f1ebb0d106bb4361e7cd167","title":"Update stack version"},{"location":"easycozy/config/","text":"Configuration This section includes all configurations available for the stack. Configuration File The stack's configuration file is located at .easy-cozy/cozystack/cozy.yml . It can be edited in order to changes various parameters, smtp, logs ... SMTP Modify the cozy.yml responsible for the configuration : mail : # mail noreply address - flags: --mail-noreply-address noreply_address : noreply @localhost noreply_name : My Cozy reply_to : support @cozycloud . cc # mail smtp host - flags: --mail-host host : smtp . home # mail smtp port - flags: --mail-port port : 465 # mail smtp username - flags: --mail-username username : {{ . Env . COZY_MAIL_USERNAME }} # mail smtp password - flags: --mail-password password : {{ . Env . COZY_MAIL_PASSWORD }} # disable mail tls - flags: --mail-disable-tls disable_tls : false # skip the certificate validation (may be useful on localhost) skip_certificate_validation : false known issue A known cozy-stack issue here causes you to have to change the above configuration with: mail: # mail smtp port - flags: --mail-port port: 587 # disable mail tls - flags: --mail-disable-tls disable_tls: true After updating configuration don't forget to restart your cozy-stack : docker-compose restart cozy","title":"Configuration"},{"location":"easycozy/config/#configuration","text":"This section includes all configurations available for the stack.","title":"Configuration"},{"location":"easycozy/config/#configuration-file","text":"The stack's configuration file is located at .easy-cozy/cozystack/cozy.yml . It can be edited in order to changes various parameters, smtp, logs ...","title":"Configuration File"},{"location":"easycozy/config/#smtp","text":"Modify the cozy.yml responsible for the configuration : mail : # mail noreply address - flags: --mail-noreply-address noreply_address : noreply @localhost noreply_name : My Cozy reply_to : support @cozycloud . cc # mail smtp host - flags: --mail-host host : smtp . home # mail smtp port - flags: --mail-port port : 465 # mail smtp username - flags: --mail-username username : {{ . Env . COZY_MAIL_USERNAME }} # mail smtp password - flags: --mail-password password : {{ . Env . COZY_MAIL_PASSWORD }} # disable mail tls - flags: --mail-disable-tls disable_tls : false # skip the certificate validation (may be useful on localhost) skip_certificate_validation : false known issue A known cozy-stack issue here causes you to have to change the above configuration with: mail: # mail smtp port - flags: --mail-port port: 587 # disable mail tls - flags: --mail-disable-tls disable_tls: true After updating configuration don't forget to restart your cozy-stack : docker-compose restart cozy","title":"SMTP"},{"location":"easycozy/known_errors/","text":"Oops... Sometime the stack get stuck when we reset several instances, overflowing our message broker rabbitmq. The following screen is then obtained when trying to access an instance: On the server, we can see that the server is underwater by using \"top\" command: To fix this issue, just restart the service on the server with \"docker-compose down / docker-compose up -d\" in the easy-cozy folder:","title":"Known errors"},{"location":"easycozy/known_errors/#oops","text":"Sometime the stack get stuck when we reset several instances, overflowing our message broker rabbitmq. The following screen is then obtained when trying to access an instance: On the server, we can see that the server is underwater by using \"top\" command: To fix this issue, just restart the service on the server with \"docker-compose down / docker-compose up -d\" in the easy-cozy folder:","title":"Oops..."},{"location":"easycozy/scripts/","text":"Scripts Easy cozy project comes with 2 main scripts: create-instance.sh: used to create an instance for a user remove-instance.sh: used to remove an instance for a specific user In addition of these scripts we have added custom scripts for some specific needs. All these scripts are available in the \"ecolyo-infra-scripts/admin_scripts\" folder Scripts for instances Scripts Args Description reset_instance.sh instance_username Remove and recreate again the instance for a given user Scripts for applications Scripts Args Description update_all_ecolyo_dev.sh none update Ecolyo with last version from build-dev branch on all instances update_ecolyo_master.sh instance_username update Ecolyo with last version from build branch on a specific instance update_ecolyo_dev.sh instance_username update Ecolyo with last version from build-dev branch on a specific instance update_ecolyo_test.sh instance_username update Ecolyo with last version from build-test branch on a specific instance update_pilote_master.sh instance_username update Pilote with last version from build-dev branch on a specific instance update_pilote_dev.sh instance_username update Pilote with last version from build-test branch on a specific instance Scripts for konnectors Scripts Args Description update_enedis_konnector_prod.sh instance_username update Enedis konnector with last version from build branch on a specific instance update_enedis_konnector_dev.sh instance_username update Enedis konnector with last version from build-dev branch on a specific instance","title":"Scripts"},{"location":"easycozy/scripts/#scripts","text":"Easy cozy project comes with 2 main scripts: create-instance.sh: used to create an instance for a user remove-instance.sh: used to remove an instance for a specific user In addition of these scripts we have added custom scripts for some specific needs. All these scripts are available in the \"ecolyo-infra-scripts/admin_scripts\" folder","title":"Scripts"},{"location":"easycozy/scripts/#scripts-for-instances","text":"Scripts Args Description reset_instance.sh instance_username Remove and recreate again the instance for a given user","title":"Scripts for instances"},{"location":"easycozy/scripts/#scripts-for-applications","text":"Scripts Args Description update_all_ecolyo_dev.sh none update Ecolyo with last version from build-dev branch on all instances update_ecolyo_master.sh instance_username update Ecolyo with last version from build branch on a specific instance update_ecolyo_dev.sh instance_username update Ecolyo with last version from build-dev branch on a specific instance update_ecolyo_test.sh instance_username update Ecolyo with last version from build-test branch on a specific instance update_pilote_master.sh instance_username update Pilote with last version from build-dev branch on a specific instance update_pilote_dev.sh instance_username update Pilote with last version from build-test branch on a specific instance","title":"Scripts for applications"},{"location":"easycozy/scripts/#scripts-for-konnectors","text":"Scripts Args Description update_enedis_konnector_prod.sh instance_username update Enedis konnector with last version from build branch on a specific instance update_enedis_konnector_dev.sh instance_username update Enedis konnector with last version from build-dev branch on a specific instance","title":"Scripts for konnectors"},{"location":"easycozy/tips/","text":"Tips Query data from an instance For maintenance reason, we sometime need to check data on a specific instance. For that we use postman to send get / post / delete data. All posibility are described in the data section of Cozy documentation . Example The example will describ how to query userChallenge data from \"ecolyotest\" instance. First, you need to be able to connect to the instance in order to retrive the bearer and the cozysessid. Then use postman to query the data: Verb: GET Request: https://ecolyotest.cozy.self-data.alpha.grandlyon.com/data/com.grandlyon.ecolyo.userchallenge/_all_docs?include_docs=true Header: Accept: application/json content-type: application/json Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Cookie: cozysessid=AAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx The result will then be retrieve by postman: { \"total_rows\": 1, \"offset\": 0, \"rows\": [ { \"id\": \"a353b985c0c5f09229b0acd6b2f37f1b\", \"key\": \"a353b985c0c5f09229b0acd6b2f37f1b\", ... ] } Delete a doctype from a instance You can use ACH to delete a doctype. Please find the ACH documentation to see all commands Example The example will describ how to drop userChallenge doctype from \"ecolyotest\" instance. the token provided is the one present in the cozysessid. $ ach -t xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -u https://ecolyotest.cozy.self-data.alpha.grandlyon.com drop com.grandlyon.ecolyo.userchallenge This doctypes will be removed. * com.grandlyon.ecolyo.userchallenge Type \"yes\" if ok. yes A browser window will be opened asking for authorization to access to your file. Just click on \"Authorize\" to keep on with the doctype dropping.","title":"Tips"},{"location":"easycozy/tips/#tips","text":"","title":"Tips"},{"location":"easycozy/tips/#query-data-from-an-instance","text":"For maintenance reason, we sometime need to check data on a specific instance. For that we use postman to send get / post / delete data. All posibility are described in the data section of Cozy documentation . Example The example will describ how to query userChallenge data from \"ecolyotest\" instance. First, you need to be able to connect to the instance in order to retrive the bearer and the cozysessid. Then use postman to query the data: Verb: GET Request: https://ecolyotest.cozy.self-data.alpha.grandlyon.com/data/com.grandlyon.ecolyo.userchallenge/_all_docs?include_docs=true Header: Accept: application/json content-type: application/json Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Cookie: cozysessid=AAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx The result will then be retrieve by postman: { \"total_rows\": 1, \"offset\": 0, \"rows\": [ { \"id\": \"a353b985c0c5f09229b0acd6b2f37f1b\", \"key\": \"a353b985c0c5f09229b0acd6b2f37f1b\", ... ] }","title":"Query data from an instance"},{"location":"easycozy/tips/#delete-a-doctype-from-a-instance","text":"You can use ACH to delete a doctype. Please find the ACH documentation to see all commands Example The example will describ how to drop userChallenge doctype from \"ecolyotest\" instance. the token provided is the one present in the cozysessid. $ ach -t xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -u https://ecolyotest.cozy.self-data.alpha.grandlyon.com drop com.grandlyon.ecolyo.userchallenge This doctypes will be removed. * com.grandlyon.ecolyo.userchallenge Type \"yes\" if ok. yes A browser window will be opened asking for authorization to access to your file. Just click on \"Authorize\" to keep on with the doctype dropping.","title":"Delete a doctype from a instance"},{"location":"ecolyo/","text":"Ecolyo is a multi-fluid application solution towards users of the grand lyon metropolis to monitor and optimize their energy consumption. Reminder If you're a new developer tasked to work on this project, please get acquainted with the team processes and read the advised dev environment documentation and the self-data prerequisites . Repositories ecolyo ecolyo-agent server ecolyo-agent client","title":"Introduction"},{"location":"ecolyo/#repositories","text":"ecolyo ecolyo-agent server ecolyo-agent client","title":"Repositories"},{"location":"ecolyo/application/deploy/","text":"Deploy This section will show you how to deploy your project on different environments. Deploy build to builds branches 3 builds branch are today available for Ecolyo: build : reflect the build of the master branch and the version deployed in production environment build-dev : reflect the build of the dev branch and the version deployed on dev environment build-test : reflect a temporary build which can be used for test purpose Windows users Some command did not run on Windows. Please use your Linux distribution installed on your WSL. For more information about it see the Install WSL section Make sure that: you are on the right branch (dev or master) depending on the enviroment you need to deploy. your branch is up to date you node modules are up to date First build the application : $ yarn build Next you can deploy the build to the target branch: # deploy on build-test branch $ yarn deploy-test # deploy on build-dev branch $ yarn deploy-dev # deploy on build branch $ yarn deploy Auto deploy for dev In order to prevent manual action for deployment, a gitlab-runner has been configured to deploy every changes on the dev branch on our test env cicd scripts You can find all scripts used in cicd jobs on the following repository Deploy build-test branch to one Scaleway instance for testing You can directly use the content of build-test branch to update one instance for test purpose. Simply use the dedicated script \"update_ecolyo_test.sh \" with the targeted instance (from the server). By default we use the ecolyotest instance for testing intermediate functionnality. For more informations you can check for Easy Cozy scripts . Deploy build-dev branch to all Scaleway instances You can directly use the content of build-dev branch to update apps on dev environment using scripts (from the server). Simply use the dedicated script \"update_all_ecolyo_dev.sh\" (from the server). For more informations you can check for Easy Cozy scripts . Deploy build branch to Cozy You can deploy content of build branch into Cozy registry by using the cozy-app-publish command after replacing following value: $REGISTRY_TOKEN : token provided by Cozy team $VERSION_NUMBER: version of the application $COZY_SPACE: space of the Cozy $ yarn cozy-app-publish --token $REGISTRY_TOKEN --build-url https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/-/archive/build/ecolyo-build.tar.gz --manual-version $VERSION_NUMBER --space $COZY_SPACE More information at cozy-app-publish/","title":"Deploy"},{"location":"ecolyo/application/deploy/#deploy","text":"This section will show you how to deploy your project on different environments.","title":"Deploy"},{"location":"ecolyo/application/deploy/#deploy-build-to-builds-branches","text":"3 builds branch are today available for Ecolyo: build : reflect the build of the master branch and the version deployed in production environment build-dev : reflect the build of the dev branch and the version deployed on dev environment build-test : reflect a temporary build which can be used for test purpose Windows users Some command did not run on Windows. Please use your Linux distribution installed on your WSL. For more information about it see the Install WSL section Make sure that: you are on the right branch (dev or master) depending on the enviroment you need to deploy. your branch is up to date you node modules are up to date First build the application : $ yarn build Next you can deploy the build to the target branch: # deploy on build-test branch $ yarn deploy-test # deploy on build-dev branch $ yarn deploy-dev # deploy on build branch $ yarn deploy","title":"Deploy build to builds branches"},{"location":"ecolyo/application/deploy/#auto-deploy-for-dev","text":"In order to prevent manual action for deployment, a gitlab-runner has been configured to deploy every changes on the dev branch on our test env cicd scripts You can find all scripts used in cicd jobs on the following repository","title":"Auto deploy for dev"},{"location":"ecolyo/application/deploy/#deploy-build-test-branch-to-one-scaleway-instance-for-testing","text":"You can directly use the content of build-test branch to update one instance for test purpose. Simply use the dedicated script \"update_ecolyo_test.sh \" with the targeted instance (from the server). By default we use the ecolyotest instance for testing intermediate functionnality. For more informations you can check for Easy Cozy scripts .","title":"Deploy build-test branch to one Scaleway instance for testing"},{"location":"ecolyo/application/deploy/#deploy-build-dev-branch-to-all-scaleway-instances","text":"You can directly use the content of build-dev branch to update apps on dev environment using scripts (from the server). Simply use the dedicated script \"update_all_ecolyo_dev.sh\" (from the server). For more informations you can check for Easy Cozy scripts .","title":"Deploy build-dev branch to all Scaleway instances"},{"location":"ecolyo/application/deploy/#deploy-build-branch-to-cozy","text":"You can deploy content of build branch into Cozy registry by using the cozy-app-publish command after replacing following value: $REGISTRY_TOKEN : token provided by Cozy team $VERSION_NUMBER: version of the application $COZY_SPACE: space of the Cozy $ yarn cozy-app-publish --token $REGISTRY_TOKEN --build-url https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/-/archive/build/ecolyo-build.tar.gz --manual-version $VERSION_NUMBER --space $COZY_SPACE More information at cozy-app-publish/","title":"Deploy build branch to Cozy"},{"location":"ecolyo/application/description/","text":"Ecolyo is a Cozy application that allows users to connect their energy accounts such as EGL , ENEDIS and GRDF , using cozy konnectors","title":"Description"},{"location":"ecolyo/application/gitflow/","text":"Initialize Create a new project in gitlab and take note of its url Protecting Master Branch On the gitlab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be using merge requests. Setting Development Branch Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/web-et-numerique/llle.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev Start Developing For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch Conventional Commits The commit contains the following structural types : fix feature In our team organisation we are using IceScrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a feature branch name should follow this structure: features/<number of the User Story>-<title_of_the_user_story> You can create the branch by typing: git checkout -b features/<number of the User Story>-<title_of_the_user_story> Note that the feature type is the only one with a dedicated folder (features/-US). Each fix branch should be named as the following fix-\\<title_of_the_fix> . You can create the branch by typing: git checkout -b fix-<title_of_the_fix> Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. Types other than fix and feature are allowed, for example build , chore , ci , docs , style , refactor , perf , test and others. add tag git tag -a 1.0.0 -m \"complementary message\" Gitflow Scheme","title":"Gitflow"},{"location":"ecolyo/application/gitflow/#initialize","text":"Create a new project in gitlab and take note of its url","title":"Initialize"},{"location":"ecolyo/application/gitflow/#protecting-master-branch","text":"On the gitlab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be using merge requests.","title":"Protecting Master Branch"},{"location":"ecolyo/application/gitflow/#setting-development-branch","text":"Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/web-et-numerique/llle.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev","title":"Setting Development Branch"},{"location":"ecolyo/application/gitflow/#start-developing","text":"For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch","title":"Start Developing"},{"location":"ecolyo/application/gitflow/#conventional-commits","text":"The commit contains the following structural types : fix feature In our team organisation we are using IceScrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a feature branch name should follow this structure: features/<number of the User Story>-<title_of_the_user_story> You can create the branch by typing: git checkout -b features/<number of the User Story>-<title_of_the_user_story> Note that the feature type is the only one with a dedicated folder (features/-US). Each fix branch should be named as the following fix-\\<title_of_the_fix> . You can create the branch by typing: git checkout -b fix-<title_of_the_fix> Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. Types other than fix and feature are allowed, for example build , chore , ci , docs , style , refactor , perf , test and others. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Conventional Commits"},{"location":"ecolyo/application/gitflow/#gitflow-scheme","text":"","title":"Gitflow Scheme"},{"location":"ecolyo/application/mail/","text":"Explenation A templating system was needed for the app. In order to make it easy to use and also responsive, two libs has been used : - Handelbars - MJML Handlebars is used as a semantic template motor. It allow us to split email template in order to reuse some parts (header, footer ...) Mjml is a lib providing a syntax allowing developpers to easly build responsive templates. Usage Scaffolding Mails templates can be found inside src/notifications . All reusable parts can be found in base folder. All stylesheet must be include inside style.hbs . Create your template Simply create your template file : template.hbs inside the notifications folder. <mj-hero background-color=\"radial-gradient(96.2% 96.2% at 50% 3.8%, #343641 0%, #1B1C22 100%)\" padding=\"17px\"> <mj-text align=\"center\" color=\"white\" padding-top=\"20px\" font-size=\"24px\" font-family=\"Lato\" font-weight=\"normal\"> <img style=\"vertical-align: middle; margin-right: 12px\" src=\"https://ecolyo.com/assets/ecolyo-icon.svg\" alt=\"Ecolyo\"/> {{title}} </mj-text> </mj-hero> How to use it ? Inside a cozy service 1) Import the mjml lib in order to compile the template. import mjml2html from 'mjml' 2) Link all the info mandatory to render your email : const template = monthlyReportTemplate({ title: 'Du nouveau dans votre espace Ecolyo !', }) 3) Build the email and send it: const mailData = { mode: 'noreply', subject: '[Ecolyo] - Votre bilan mensuel', parts: [ { type: 'text/html', body: mjml2html(template).html, }, ], } mailService.SendMail(client, mailData) Inside the app It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why wy need to change the import for mjml lib into : const mjml2html = require('mjml-browser') Usefull links Mjml live editor","title":"Mail"},{"location":"ecolyo/application/mail/#explenation","text":"A templating system was needed for the app. In order to make it easy to use and also responsive, two libs has been used : - Handelbars - MJML Handlebars is used as a semantic template motor. It allow us to split email template in order to reuse some parts (header, footer ...) Mjml is a lib providing a syntax allowing developpers to easly build responsive templates.","title":"Explenation"},{"location":"ecolyo/application/mail/#usage","text":"","title":"Usage"},{"location":"ecolyo/application/mail/#scaffolding","text":"Mails templates can be found inside src/notifications . All reusable parts can be found in base folder. All stylesheet must be include inside style.hbs .","title":"Scaffolding"},{"location":"ecolyo/application/mail/#create-your-template","text":"Simply create your template file : template.hbs inside the notifications folder. <mj-hero background-color=\"radial-gradient(96.2% 96.2% at 50% 3.8%, #343641 0%, #1B1C22 100%)\" padding=\"17px\"> <mj-text align=\"center\" color=\"white\" padding-top=\"20px\" font-size=\"24px\" font-family=\"Lato\" font-weight=\"normal\"> <img style=\"vertical-align: middle; margin-right: 12px\" src=\"https://ecolyo.com/assets/ecolyo-icon.svg\" alt=\"Ecolyo\"/> {{title}} </mj-text> </mj-hero>","title":"Create your template"},{"location":"ecolyo/application/mail/#how-to-use-it","text":"","title":"How to use it ?"},{"location":"ecolyo/application/mail/#inside-a-cozy-service","text":"1) Import the mjml lib in order to compile the template. import mjml2html from 'mjml' 2) Link all the info mandatory to render your email : const template = monthlyReportTemplate({ title: 'Du nouveau dans votre espace Ecolyo !', }) 3) Build the email and send it: const mailData = { mode: 'noreply', subject: '[Ecolyo] - Votre bilan mensuel', parts: [ { type: 'text/html', body: mjml2html(template).html, }, ], } mailService.SendMail(client, mailData)","title":"Inside a cozy service"},{"location":"ecolyo/application/mail/#inside-the-app","text":"It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why wy need to change the import for mjml lib into : const mjml2html = require('mjml-browser')","title":"Inside the app"},{"location":"ecolyo/application/mail/#usefull-links","text":"Mjml live editor","title":"Usefull links"},{"location":"ecolyo/application/redux/","text":"Redux There are two main store created for this app: Cozy: store information about cozy (konnectors, accounts, settings, db) Ecolyo: store all states used for this app For a better state management, combineReducers(reducers) is used to split the reducing function into seperate functions. So, each managing independent parts of the state. Ecolyo Store Structure Reducer Type Description global GlobalState store global states such as: notification, type device or fluid type GlobalState enum - screenType = ScreenType - challengeExplorationNotification = boolean releaseNotes = ReleaseNotes termsStatus = TermsStatus openPartnersIssueModal = boolean - challengeActionNotification = boolean - challengeDuelNotification = boolean - analysisNotification = boolean - fluidStatus = FluidStatus[] - fluidTypes = FluidType[] profile Profile store states about profile information such as: notification, connectionDate profileType ProfileTypeState store states about user's profileType filled through the profile form profileEcogesture ProfileEcogestureState store states about user's profileEcogesture filled through the profile ecogesture form chart ChartState store consumption chart states such as: timeStep, graph data ChartState enum - selectedDate = DateTime - currentTimeStep = TimeStep - currentIndex = number - currentDatachart = Datachart - currentDatachartIndex = number - loading = boolean modal ModalState store opening state of the feedback modal ModalState enum - isFeedbacksOpen = boolean challenge ChallengeState store challenge state such as: list of user challenge, data load and current challenge ChallengeState enum - userChallengeList = UserChallenge[] - currentChallenge = UserChallenge - currentDataload = Dataload[] Updating state process Redux-thunk middleware is configured. For now, it is used only for updating the profile. To update a state, a webservice method is called before trigger a state change inside the store.","title":"Redux"},{"location":"ecolyo/application/redux/#redux","text":"There are two main store created for this app: Cozy: store information about cozy (konnectors, accounts, settings, db) Ecolyo: store all states used for this app For a better state management, combineReducers(reducers) is used to split the reducing function into seperate functions. So, each managing independent parts of the state.","title":"Redux"},{"location":"ecolyo/application/redux/#ecolyo-store-structure","text":"Reducer Type Description global GlobalState store global states such as: notification, type device or fluid type GlobalState enum - screenType = ScreenType - challengeExplorationNotification = boolean releaseNotes = ReleaseNotes termsStatus = TermsStatus openPartnersIssueModal = boolean - challengeActionNotification = boolean - challengeDuelNotification = boolean - analysisNotification = boolean - fluidStatus = FluidStatus[] - fluidTypes = FluidType[] profile Profile store states about profile information such as: notification, connectionDate profileType ProfileTypeState store states about user's profileType filled through the profile form profileEcogesture ProfileEcogestureState store states about user's profileEcogesture filled through the profile ecogesture form chart ChartState store consumption chart states such as: timeStep, graph data ChartState enum - selectedDate = DateTime - currentTimeStep = TimeStep - currentIndex = number - currentDatachart = Datachart - currentDatachartIndex = number - loading = boolean modal ModalState store opening state of the feedback modal ModalState enum - isFeedbacksOpen = boolean challenge ChallengeState store challenge state such as: list of user challenge, data load and current challenge ChallengeState enum - userChallengeList = UserChallenge[] - currentChallenge = UserChallenge - currentDataload = Dataload[]","title":"Ecolyo Store Structure"},{"location":"ecolyo/application/redux/#updating-state-process","text":"Redux-thunk middleware is configured. For now, it is used only for updating the profile. To update a state, a webservice method is called before trigger a state change inside the store.","title":"Updating state process"},{"location":"ecolyo/application/release/","text":"Release This section will show you how to properly create a release for the app. Conventionnal commit The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. The commit message should be structured as follows: <type>[optional scope]: <description> [optional body] [optional footer(s)] The commit contains the following structural elements, to communicate intent to the consumers of your library: fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning). feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning). BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type. types other than fix: and feat: are allowed, for example @commitlint/config-conventional (based on the the Angular convention) recommends build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others. footers other than BREAKING CHANGE: may be provided and follow a convention similar to git trailer format. standard-version Standard-version is librairie javascript that allow to handle easly tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and upadte changelog file. yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0) Usefull links Conventional commit doc Lib link","title":"Release"},{"location":"ecolyo/application/release/#release","text":"This section will show you how to properly create a release for the app.","title":"Release"},{"location":"ecolyo/application/release/#conventionnal-commit","text":"The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. The commit message should be structured as follows: <type>[optional scope]: <description> [optional body] [optional footer(s)] The commit contains the following structural elements, to communicate intent to the consumers of your library: fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning). feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning). BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type. types other than fix: and feat: are allowed, for example @commitlint/config-conventional (based on the the Angular convention) recommends build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others. footers other than BREAKING CHANGE: may be provided and follow a convention similar to git trailer format.","title":"Conventionnal commit"},{"location":"ecolyo/application/release/#standard-version","text":"Standard-version is librairie javascript that allow to handle easly tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and upadte changelog file. yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0)","title":"standard-version"},{"location":"ecolyo/application/release/#usefull-links","text":"Conventional commit doc Lib link","title":"Usefull links"},{"location":"ecolyo/application/scaffolding/","text":"In this section, you will find information about the project file structure and the purpose of the main folders. Source Files Folder/File Purpose assets The application's assets, contains fonts, svg and png files components The application's components. components/CommonKit In this folder you'll find global components such as Buttons, Cards, Icons, etc... Many of these components are overrided material-ui components components/Hooks This folder contains the hooks of the application components/App.tsx The root component, it calls the Routes component constants This folder contains constants files such as config.json for the konnectors fluid config, connexionWaitingText.json for the sentences displayed while fetching fluid data, and a folder consumptionConstants that contains json files with constants for consumption calculation and comparison db In this folder, you'll find JSON data used for challenges, ecogestures, and the FAQ. doctypes This folder contains the cozy doctypes, you can see more on Cozy Documentation enum This folder contains all enums like Fluid types, Screen types, and Timesteps. locales This folder contains JSON data used by the translation system i18n provided by Cozy-ui migrations This folder contains all migrations models This folder contains all models notifications This folder contains all mail notifications services This folder contains all the services store This folder contains all actions and reducers classified by component styles The styles folder you'll find a base folder that contains our variables and a components folder that contains components styles targets types utils In this folder you'll find utilitaries methods Configuration Files Folder/File Purpose .eslintrc.js Config file for ESLint gitlab-ci.yml Config file used for Gitlab continuous integration .prettierrc Config file for Prettier extension jest.config.js Config file used by Jest for testing the application manifest.webapp Manifest of the application, used by cozy for the managment of permissions, you can add permissions for doctypes there tsconfig.json Config file for TypeScript","title":"Scaffolding"},{"location":"ecolyo/application/scaffolding/#source-files","text":"Folder/File Purpose assets The application's assets, contains fonts, svg and png files components The application's components. components/CommonKit In this folder you'll find global components such as Buttons, Cards, Icons, etc... Many of these components are overrided material-ui components components/Hooks This folder contains the hooks of the application components/App.tsx The root component, it calls the Routes component constants This folder contains constants files such as config.json for the konnectors fluid config, connexionWaitingText.json for the sentences displayed while fetching fluid data, and a folder consumptionConstants that contains json files with constants for consumption calculation and comparison db In this folder, you'll find JSON data used for challenges, ecogestures, and the FAQ. doctypes This folder contains the cozy doctypes, you can see more on Cozy Documentation enum This folder contains all enums like Fluid types, Screen types, and Timesteps. locales This folder contains JSON data used by the translation system i18n provided by Cozy-ui migrations This folder contains all migrations models This folder contains all models notifications This folder contains all mail notifications services This folder contains all the services store This folder contains all actions and reducers classified by component styles The styles folder you'll find a base folder that contains our variables and a components folder that contains components styles targets types utils In this folder you'll find utilitaries methods","title":"Source Files"},{"location":"ecolyo/application/scaffolding/#configuration-files","text":"Folder/File Purpose .eslintrc.js Config file for ESLint gitlab-ci.yml Config file used for Gitlab continuous integration .prettierrc Config file for Prettier extension jest.config.js Config file used by Jest for testing the application manifest.webapp Manifest of the application, used by cozy for the managment of permissions, you can add permissions for doctypes there tsconfig.json Config file for TypeScript","title":"Configuration Files"},{"location":"ecolyo/ecolyo-agent/introduction/","text":"Ecolyo-Agent is a backoffice for the Ecolyo app that allows to create and edit content for the newsletters sent to the users This project is split into two parts: backend and frontend; each has its own repository If you are a new developper tasked to work on this project, check the setup your environment and launch the application on local to start the application. Repositories Ecolyo-Agent backend gitlab repository Ecolyo-Agent frontend gitlab repository","title":"Introduction"},{"location":"ecolyo/ecolyo-agent/introduction/#repositories","text":"Ecolyo-Agent backend gitlab repository Ecolyo-Agent frontend gitlab repository","title":"Repositories"},{"location":"ecolyo/ecolyo-agent/development/backup/","text":"Principles In the docker-compose.yml, there is a service called \"database-backup\" whose only purpose is to run automatic backups of the database. It is running a crontab that execute the backup.sh script every day at midnight. The dump of the database are stored in folders name like this : \"ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND\". Only the 14 last days are stored. The location of the backup folder on the server is specified in the volumes of the \"database-backup\" service, in the docker-compose file. Backup manually To backup manually, run this command : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/backup.sh Restore manually To restore a specific dump, run this command replacing YEAR etc.. by the date of the wanted backup : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/restore.sh ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND","title":"Backup"},{"location":"ecolyo/ecolyo-agent/development/backup/#principles","text":"In the docker-compose.yml, there is a service called \"database-backup\" whose only purpose is to run automatic backups of the database. It is running a crontab that execute the backup.sh script every day at midnight. The dump of the database are stored in folders name like this : \"ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND\". Only the 14 last days are stored. The location of the backup folder on the server is specified in the volumes of the \"database-backup\" service, in the docker-compose file.","title":"Principles"},{"location":"ecolyo/ecolyo-agent/development/backup/#backup-manually","text":"To backup manually, run this command : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/backup.sh","title":"Backup manually"},{"location":"ecolyo/ecolyo-agent/development/backup/#restore-manually","text":"To restore a specific dump, run this command replacing YEAR etc.. by the date of the wanted backup : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/restore.sh ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND","title":"Restore manually"},{"location":"ecolyo/ecolyo-agent/development/deploy/","text":"This section will allow you to properly deploy Ecolyo-Agent in a production environment Deploy Ecolyo-Agent application To deploy ecolyo-agent application in a production environment, you need to create docker-compose.yml, site.conf and .env files docker-compose.yml version: '3.7' services: nginx: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client:dev restart: unless-stopped ports: - 8080:8080 depends_on: - backend networks: backoffice: volumes: - ./site.conf:/etc/nginx/conf.d/default.conf - ./image-lib:/usr/share/nginx/html/lib database-agent: image: mysql:5 ports: - 3306:3306 networks: backoffice: restart: always environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} healthcheck: test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD interval: 5s timeout: 10s retries: 60 database-backup: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:db-backup networks: backoffice: environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} volumes: - /mnt/local/data/backup:/backup restart: unless-stopped depends_on: database-agent: condition: service_healthy backend: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:dev networks: backoffice: depends_on: database-agent: condition: service_healthy restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ./configs:/app/configs - ./letsencrypt_cache:/app/letsencrypt_cache - ./data:/app/data - ./${IMAGE_FOLDER}:/app/${IMAGE_FOLDER} ports: - ${HTTPS_PORT}:${HTTPS_PORT} - 8190:8090 environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} - CLIENT_SECRET=${CLIENT_SECRET} - AUTH_URL=${AUTH_URL} - IMAGE_FOLDER=${IMAGE_FOLDER} - MOCK_OAUTH2=${MOCK_OAUTH2} - TOKEN_URL=${TOKEN_URL} - USERINFO_URL=${USERINFO_URL} - DEBUG_MODE=${DEBUG_MODE} - DATABASE_USER=${DATABASE_USER} - DATABASE_NAME=${DATABASE_NAME} - DATABASE_PASSWORD=${DATABASE_PASSWORD} - DATABASE_HOST=database-agent networks: backoffice: site.conf server { listen 8080; server_name ecolyo-agent.grandlyon.com; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html =404; } location /api { proxy_pass https://backend:1443/api; } location /OAuth2Login { proxy_pass https://backend:1443/OAuth2Login; } location /OAuth2Callback { proxy_pass https://backend:1443/OAuth2Callback; } location /Logout { proxy_pass https://backend:1443/Logout; } location /swagger { proxy_pass https://backend:1443/swagger; } location /imageNames { proxy_pass https://backend:1443/api/admin/imageNames; } # cozy-doctypes workaround location /email { # if ($arg_serviceName != overview) { return 404; } if ($arg_param !~ \"^\\d+$\") { return 404; } if ($arg_serviceName = \"image\") { rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; #} proxy_pass https://backend:1443/api/common/monthlyReport/$arg_param; # rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; } location ~ ^/assets/(.+\\.(?:gif|jpe?g|svg|png))$ { alias /usr/share/nginx/html/lib/$1; gzip_static on; expires max; add_header Cache-Control public; } } .env In this file, add the variables as described in the env-template file in the git repository To use OAuth2 login ask your client ID and client secret Here is the config to run the app NODE_TLS_REJECT_UNAUTHORIZED = '0' HTTPS=true SSL_CRT_FILE=cert.pem SSL_KEY_FILE=key.pem # Common settings HOSTNAME=your_url.com ADMIN_ROLE=****** DEBUG_MODE=false MOCK_OAUTH2=false HTTPS_PORT=1443 IMAGE_FOLDER=image-lib # Needed to user OAuth2 authentication : REDIRECT_URL=https://${HOSTNAME}:443/OAuth2Callback CLIENT_ID=**get one from your IDP** CLIENT_SECRET=**get one from your IDP** AUTH_URL=**get it from your IDP** TOKEN_URL=**get it from your IDP** USERINFO_URL=**get it from your IDP** LOGOUT_URL=/ # Access to the database DATABASE_USER=****** DATABASE_PASSWORD=******* DATABASE_NAME=backoffice Start the application Then start the app by launching the command : docker-compose up -d To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set","title":"Deploy"},{"location":"ecolyo/ecolyo-agent/development/deploy/#deploy-ecolyo-agent-application","text":"To deploy ecolyo-agent application in a production environment, you need to create docker-compose.yml, site.conf and .env files","title":"Deploy Ecolyo-Agent application"},{"location":"ecolyo/ecolyo-agent/development/deploy/#docker-composeyml","text":"version: '3.7' services: nginx: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client:dev restart: unless-stopped ports: - 8080:8080 depends_on: - backend networks: backoffice: volumes: - ./site.conf:/etc/nginx/conf.d/default.conf - ./image-lib:/usr/share/nginx/html/lib database-agent: image: mysql:5 ports: - 3306:3306 networks: backoffice: restart: always environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} healthcheck: test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD interval: 5s timeout: 10s retries: 60 database-backup: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:db-backup networks: backoffice: environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} volumes: - /mnt/local/data/backup:/backup restart: unless-stopped depends_on: database-agent: condition: service_healthy backend: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:dev networks: backoffice: depends_on: database-agent: condition: service_healthy restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ./configs:/app/configs - ./letsencrypt_cache:/app/letsencrypt_cache - ./data:/app/data - ./${IMAGE_FOLDER}:/app/${IMAGE_FOLDER} ports: - ${HTTPS_PORT}:${HTTPS_PORT} - 8190:8090 environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} - CLIENT_SECRET=${CLIENT_SECRET} - AUTH_URL=${AUTH_URL} - IMAGE_FOLDER=${IMAGE_FOLDER} - MOCK_OAUTH2=${MOCK_OAUTH2} - TOKEN_URL=${TOKEN_URL} - USERINFO_URL=${USERINFO_URL} - DEBUG_MODE=${DEBUG_MODE} - DATABASE_USER=${DATABASE_USER} - DATABASE_NAME=${DATABASE_NAME} - DATABASE_PASSWORD=${DATABASE_PASSWORD} - DATABASE_HOST=database-agent networks: backoffice:","title":"docker-compose.yml"},{"location":"ecolyo/ecolyo-agent/development/deploy/#siteconf","text":"server { listen 8080; server_name ecolyo-agent.grandlyon.com; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html =404; } location /api { proxy_pass https://backend:1443/api; } location /OAuth2Login { proxy_pass https://backend:1443/OAuth2Login; } location /OAuth2Callback { proxy_pass https://backend:1443/OAuth2Callback; } location /Logout { proxy_pass https://backend:1443/Logout; } location /swagger { proxy_pass https://backend:1443/swagger; } location /imageNames { proxy_pass https://backend:1443/api/admin/imageNames; } # cozy-doctypes workaround location /email { # if ($arg_serviceName != overview) { return 404; } if ($arg_param !~ \"^\\d+$\") { return 404; } if ($arg_serviceName = \"image\") { rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; #} proxy_pass https://backend:1443/api/common/monthlyReport/$arg_param; # rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; } location ~ ^/assets/(.+\\.(?:gif|jpe?g|svg|png))$ { alias /usr/share/nginx/html/lib/$1; gzip_static on; expires max; add_header Cache-Control public; } }","title":"site.conf"},{"location":"ecolyo/ecolyo-agent/development/deploy/#env","text":"In this file, add the variables as described in the env-template file in the git repository To use OAuth2 login ask your client ID and client secret Here is the config to run the app NODE_TLS_REJECT_UNAUTHORIZED = '0' HTTPS=true SSL_CRT_FILE=cert.pem SSL_KEY_FILE=key.pem # Common settings HOSTNAME=your_url.com ADMIN_ROLE=****** DEBUG_MODE=false MOCK_OAUTH2=false HTTPS_PORT=1443 IMAGE_FOLDER=image-lib # Needed to user OAuth2 authentication : REDIRECT_URL=https://${HOSTNAME}:443/OAuth2Callback CLIENT_ID=**get one from your IDP** CLIENT_SECRET=**get one from your IDP** AUTH_URL=**get it from your IDP** TOKEN_URL=**get it from your IDP** USERINFO_URL=**get it from your IDP** LOGOUT_URL=/ # Access to the database DATABASE_USER=****** DATABASE_PASSWORD=******* DATABASE_NAME=backoffice","title":".env"},{"location":"ecolyo/ecolyo-agent/development/deploy/#start-the-application","text":"Then start the app by launching the command : docker-compose up -d To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set","title":"Start the application"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/","text":"This section will allow you to import the assets used in the newletters from Ecolyo Import assets In the rec or prod server, in the folder scripts , there is the following script, named import-convert-assets.sh . #!/bin/bash # Get env variables . ../.env EMAIL_ASSETS_PATH = \"src/assets/icons/email\" ECOGESTURE_ASSETS_PATH = \"src/assets/icons/visu/ecogesture\" EXPORT_FORMAT = \".png\" pwd = $( pwd ) # Fetch and convert email assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= ${ EMAIL_ASSETS_PATH } \" --output email.tar.gz tar -xf email.tar.gz cd *-email/ $EMAIL_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) $file ; done && rm *.svg cd $pwd # Fetch and convert ecogesture assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= $ECOGESTURE_ASSETS_PATH \" --output ecogesture.tar.gz tar -xf ecogesture.tar.gz cd *-ecogesture/ $ECOGESTURE_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) ${ file } ; done && rm *.svg # Cleanup cd $pwd rm -rf ../ $IMAGE_FOLDER mv *-email/ $EMAIL_ASSETS_PATH ../ $IMAGE_FOLDER mv *-ecogesture/ $ECOGESTURE_ASSETS_PATH ../ $IMAGE_FOLDER /ecogesture rm -rf email.tar.gz ecogesture.tar.gz *-email *-ecogesture # Give ownership to container user chown -R 1000 :1000 ../ $IMAGE_FOLDER To import assets for the ecogesture images, run (inside of scripts folder) sudo sh import-convert-assets.sh Check that a \"image-lib\" folder has been created, that it contains a \"ecogesture\" folder and some PNG images and that the owner of the \"image-lib\" folder is the user id 1000.","title":"Handle assets"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#import-assets","text":"In the rec or prod server, in the folder scripts , there is the following script, named import-convert-assets.sh . #!/bin/bash # Get env variables . ../.env EMAIL_ASSETS_PATH = \"src/assets/icons/email\" ECOGESTURE_ASSETS_PATH = \"src/assets/icons/visu/ecogesture\" EXPORT_FORMAT = \".png\" pwd = $( pwd ) # Fetch and convert email assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= ${ EMAIL_ASSETS_PATH } \" --output email.tar.gz tar -xf email.tar.gz cd *-email/ $EMAIL_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) $file ; done && rm *.svg cd $pwd # Fetch and convert ecogesture assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= $ECOGESTURE_ASSETS_PATH \" --output ecogesture.tar.gz tar -xf ecogesture.tar.gz cd *-ecogesture/ $ECOGESTURE_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) ${ file } ; done && rm *.svg # Cleanup cd $pwd rm -rf ../ $IMAGE_FOLDER mv *-email/ $EMAIL_ASSETS_PATH ../ $IMAGE_FOLDER mv *-ecogesture/ $ECOGESTURE_ASSETS_PATH ../ $IMAGE_FOLDER /ecogesture rm -rf email.tar.gz ecogesture.tar.gz *-email *-ecogesture # Give ownership to container user chown -R 1000 :1000 ../ $IMAGE_FOLDER To import assets for the ecogesture images, run (inside of scripts folder) sudo sh import-convert-assets.sh Check that a \"image-lib\" folder has been created, that it contains a \"ecogesture\" folder and some PNG images and that the owner of the \"image-lib\" folder is the user id 1000.","title":"Import assets"},{"location":"ecolyo/ecolyo-agent/functionalities/authentification/","text":"Authentification This backoffice is meant to be used only by the admins of Ecolyo app and so they need to login to edit the newsletters. The protocol used to login is OAuth2 with the Authorization Code grant type ( more info ) Once an admin is connected, he must call the /whoAmI route to access his XSRF-TOKEN and add it in a header named \"XSRF-TOKEN\" for all requests going to the backend. The only routes that can be accessed without authentification are /monthlyReport/year/month and /monthlyReport with GET. They will return all the different sections of a specific or the current newsletter in a single JSON.","title":"Authentification"},{"location":"ecolyo/ecolyo-agent/functionalities/authentification/#authentification","text":"This backoffice is meant to be used only by the admins of Ecolyo app and so they need to login to edit the newsletters. The protocol used to login is OAuth2 with the Authorization Code grant type ( more info ) Once an admin is connected, he must call the /whoAmI route to access his XSRF-TOKEN and add it in a header named \"XSRF-TOKEN\" for all requests going to the backend. The only routes that can be accessed without authentification are /monthlyReport/year/month and /monthlyReport with GET. They will return all the different sections of a specific or the current newsletter in a single JSON.","title":"Authentification"},{"location":"ecolyo/ecolyo-agent/functionalities/general/","text":"Introduction Newsletter The goal is to send newsletters following this design : There are 4 different sections : subject : manages the mail subject monthlyInfo : contains a image URL and some global information monthlyNews : contains an editable title and some information about the novelties poll : contains a question and a link to answer a survey Partners issues This section allow the admin to activate alerts in the ecolyo app when a partners API is down. Admin has to activate the modal switch AND at least one fluid switch to make it work. He also has to set the switches to off position manually when the concerned APIs are back to normal Prices This section manages the prices for each fluid in the ecolyo application. Rules The next price to create is automatically pre-selected by default Only the 2 last prices plus the one to create are editable, the others are just consultable Each fluid has its own date frequency : Electricity : one new price every 6 month (February and August) Water : one new price every year Gas : one new price every month When user creates a new price, the previous price's endDate is set to the new startDate minus 1 minute, so every prices keeps following in time.","title":"General"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#introduction","text":"","title":"Introduction"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#newsletter","text":"The goal is to send newsletters following this design : There are 4 different sections : subject : manages the mail subject monthlyInfo : contains a image URL and some global information monthlyNews : contains an editable title and some information about the novelties poll : contains a question and a link to answer a survey","title":"Newsletter"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#partners-issues","text":"This section allow the admin to activate alerts in the ecolyo app when a partners API is down. Admin has to activate the modal switch AND at least one fluid switch to make it work. He also has to set the switches to off position manually when the concerned APIs are back to normal","title":"Partners issues"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#prices","text":"This section manages the prices for each fluid in the ecolyo application.","title":"Prices"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#rules","text":"The next price to create is automatically pre-selected by default Only the 2 last prices plus the one to create are editable, the others are just consultable Each fluid has its own date frequency : Electricity : one new price every 6 month (February and August) Water : one new price every year Gas : one new price every month When user creates a new price, the previous price's endDate is set to the new startDate minus 1 minute, so every prices keeps following in time.","title":"Rules"},{"location":"ecolyo/ecolyo-agent/functionalities/routes/","text":"Routes The different routes exposed by the backend are described by Swagger documentation. Once the appis deployed, the documentation is accessible at https://HOSTNAME/swagger/index.html","title":"Routes"},{"location":"ecolyo/ecolyo-agent/functionalities/routes/#routes","text":"The different routes exposed by the backend are described by Swagger documentation. Once the appis deployed, the documentation is accessible at https://HOSTNAME/swagger/index.html","title":"Routes"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/","text":"This section will allow you to launch a proper local environment for Ecolyo-Agent Initialisation of the project Clone the project repository Use following commands in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server Installation of the project Installation of node modules To install required node module, open a terminal on the root folder of the backoffice-client project and type the following command: yarn install Local usage Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member. In order to launch the projet in local with the backend working launch the following command yarn local-up This command will launch the app from the docker-compose.local.yml file, which will launch 3 docker images and start the react app with yarn start The backend Go app, from the image located on its GitLab repository The mongo Database, from the DockerHub image The Ngnix server with a local configuration located in nginx/site.conf To stop it properly use yarn local-down This app runs in https, such as the backend, to access it go on https://localhost/ Also make sure you have HTTPS env variable set to true. Do not use the app with the port 3000, you won't be able to login. If you are launching the project from a Windows OS : Make sure to comment the 'extra_hosts' lines in the docker-compose.local file. Otherwise, you you won't be able to access your machine's localhost from the docker container. Backend and Database In order to get Backend documentation, please refer directly to the backend project Nginx The nginx server redirects https requests from frontend to the backend on port 1443. It has two configuration files : nginx/site.conf, used for local development nginx/site.prod.conf, used for production The nginx server needs local ssl certificates in order to run an interact with backend, these certificates are present in the project. Check success To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set Mock OAuth2 server Listening on: http://localhost:8090 Once the application is started, you can access it here: https://localhost Test on alpha In order to test the app on alpha you can do the following steps: Build locally your docker image for the client and/or the server docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag - Push the image docker push registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag Connect to alpha in ssh, go to ecolyo-agent > docker-compose.yml and change the image tag for client and/or server Then launch the app, it will pull automatically the new images docker-compose up -d If you have access denied issue, try to docker login docker login registry.forge.grandlyon.com/web-et-numerique/llle_project/ If you want to update alpha using the same image tag with edited image, just pull manually your new image and rebuild the concerned image docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag docker-compose up -d If you need to work with prices on alpha, you will need to init the prices database. First get the mysql container id docker ps Then get into the container docker exec -it <container-id> bash Then execute the mysql script that imports all the prices in DB mysql --local-infile=1 -uroot -p backoffice < /dbinit/dbinit.sql You will be prompted for the admin password, use the db password set in the .env file. Now you're ready to edit your prices on alpha !","title":"Launch the application on local"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following commands in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server","title":"Clone the project repository"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#installation-of-node-modules","text":"To install required node module, open a terminal on the root folder of the backoffice-client project and type the following command: yarn install","title":"Installation of node modules"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#local-usage","text":"Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member. In order to launch the projet in local with the backend working launch the following command yarn local-up This command will launch the app from the docker-compose.local.yml file, which will launch 3 docker images and start the react app with yarn start The backend Go app, from the image located on its GitLab repository The mongo Database, from the DockerHub image The Ngnix server with a local configuration located in nginx/site.conf To stop it properly use yarn local-down This app runs in https, such as the backend, to access it go on https://localhost/ Also make sure you have HTTPS env variable set to true. Do not use the app with the port 3000, you won't be able to login. If you are launching the project from a Windows OS : Make sure to comment the 'extra_hosts' lines in the docker-compose.local file. Otherwise, you you won't be able to access your machine's localhost from the docker container.","title":"Local usage"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#backend-and-database","text":"In order to get Backend documentation, please refer directly to the backend project","title":"Backend and Database"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#nginx","text":"The nginx server redirects https requests from frontend to the backend on port 1443. It has two configuration files : nginx/site.conf, used for local development nginx/site.prod.conf, used for production The nginx server needs local ssl certificates in order to run an interact with backend, these certificates are present in the project.","title":"Nginx"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#check-success","text":"To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set Mock OAuth2 server Listening on: http://localhost:8090 Once the application is started, you can access it here: https://localhost","title":"Check success"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#test-on-alpha","text":"In order to test the app on alpha you can do the following steps: Build locally your docker image for the client and/or the server docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag - Push the image docker push registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag Connect to alpha in ssh, go to ecolyo-agent > docker-compose.yml and change the image tag for client and/or server Then launch the app, it will pull automatically the new images docker-compose up -d If you have access denied issue, try to docker login docker login registry.forge.grandlyon.com/web-et-numerique/llle_project/ If you want to update alpha using the same image tag with edited image, just pull manually your new image and rebuild the concerned image docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag docker-compose up -d If you need to work with prices on alpha, you will need to init the prices database. First get the mysql container id docker ps Then get into the container docker exec -it <container-id> bash Then execute the mysql script that imports all the prices in DB mysql --local-infile=1 -uroot -p backoffice < /dbinit/dbinit.sql You will be prompted for the admin password, use the db password set in the .env file. Now you're ready to edit your prices on alpha !","title":"Test on alpha"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/","text":"Libraries For this project, we use the libraries below: React Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM Axios HTTP client library It allows to send HTTP request and manage the responses. Lodash javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions Jest Testing library It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product. Sass CSS preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations. Gorilla/Mux Package for Go that implements a request router and dispatcher for matching incoming requests to their respective handler. It allows us to easily create and manage routes/APIs Swag Package fo Go that converts annotations to Swagger Documentation 2.0. Gorm ORM for Go It allows us to easily communicate between the backend and a relational database","title":"Libraries"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#libraries","text":"For this project, we use the libraries below:","title":"Libraries"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#react","text":"Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM","title":"React"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#axios","text":"HTTP client library It allows to send HTTP request and manage the responses.","title":"Axios"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#lodash","text":"javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions","title":"Lodash"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#jest","text":"Testing library It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product.","title":"Jest"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#sass","text":"CSS preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.","title":"Sass"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#gorillamux","text":"Package for Go that implements a request router and dispatcher for matching incoming requests to their respective handler. It allows us to easily create and manage routes/APIs","title":"Gorilla/Mux"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#swag","text":"Package fo Go that converts annotations to Swagger Documentation 2.0.","title":"Swag"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#gorm","text":"ORM for Go It allows us to easily communicate between the backend and a relational database","title":"Gorm"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/","text":"This section will allow you to install a proper local environment step by step for Ecolyo-Agent using VSCode IDE. VSCode Install VSCode Installation for VSCode can be found here: Installation of VSCode . Extensions Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Go Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension) User settings Open the project with VSCode and add the following code into .vscode/settings.json: { \"workbench.colorCustomizations\": { /* Put anything you like here */ }, \"editor.snippetSuggestions\": \"top\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"editor.formatOnPaste\": true } If this file is not empty, you can simply add the following lines to it: \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, Git The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git (current version : 1.17) Node For this project, Node version 14 is required.Download node-v14 . Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Yarn Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn . Docker Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code. Install Docker Installation of Docker can be found here: Installation of Docker . Install Docker-Compose Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose . Golang Golang (or Go for short) is an open source programming language that makes it easy to build simple, reliable, and efficient software. It is used in this project for the backend. Installation of Go (according to your OS) is explained here: Installation of Go (current version: 1.17).","title":"Setup your environment"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#vscode","text":"","title":"VSCode"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-vscode","text":"Installation for VSCode can be found here: Installation of VSCode .","title":"Install VSCode"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#extensions","text":"Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Go Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension)","title":"Extensions"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#user-settings","text":"Open the project with VSCode and add the following code into .vscode/settings.json: { \"workbench.colorCustomizations\": { /* Put anything you like here */ }, \"editor.snippetSuggestions\": \"top\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"editor.formatOnPaste\": true } If this file is not empty, you can simply add the following lines to it: \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0,","title":"User settings"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#git","text":"The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git (current version : 1.17)","title":"Git"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#node","text":"For this project, Node version 14 is required.Download node-v14 . Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine.","title":"Node"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#yarn","text":"Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn .","title":"Yarn"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#docker","text":"Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.","title":"Docker"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-docker","text":"Installation of Docker can be found here: Installation of Docker .","title":"Install Docker"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-docker-compose","text":"Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Install Docker-Compose"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#golang","text":"Golang (or Go for short) is an open source programming language that makes it easy to build simple, reliable, and efficient software. It is used in this project for the backend. Installation of Go (according to your OS) is explained here: Installation of Go (current version: 1.17).","title":"Golang"},{"location":"ecolyo/functionalities/analysis/","text":"This section explains the analysis screen and how information are displayed. Description The analysis screen shows the user a recap of his consumption of the last month. It allows him to compare his consumption with the previous month and also with an average consumption based on his profile if he completed it. Graph On the left side, the user can see his consumption for the konnected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate. Also, when user has the possibility to switch the comparison with the average profile or the ideal profile. For now, the ideal profile just represents the average profile's consumption minus 10%. Each line of the graph is handled by the AnalysisConsumptionRow component. It displays the consumption for a given fluid, a draws a bar sized in comparison with the total and applies the 10% ideal coefficient when user clicks on his ideal consumption. Note that only the consumption related to a connected fluid are taken for the calculation of the total price of the ideal or average consumption, even if the consumption indicators are shown for the non-connected fluids. (it is given a indicator for the user, considering he may use this fluid but doesn't have a connected device) Calculation The Consumption Service allows us to get the user's consumption on the given month, and the Performance Indicator Service allows us to get the comparative indicator between the currently displayed month and the previous one. In order to get the accurate consumption estimation, we use the fluidForecast stored in the user's profile. You can see more about it in the next section : ProfileType Navigation Users have the possibility to navigate between current and previous analysis, month by month, using the DateNavigator at the top of the screen. It is not possible to navigate after the last analysis (which is set the next month + 3 days in order to have a month with complete data). For example, the 3rd of June, a user will be able to see his analysis of Mai. Users won't be blocked to navigate in previous dates, and if there is no analysis to display, we use the same behavior than in the graph : we display dashes instead of data. Notification Each month, the user will receive a notification to inform him he can consult his new analysis if he activated it in the option page.","title":"Analysis"},{"location":"ecolyo/functionalities/analysis/#description","text":"The analysis screen shows the user a recap of his consumption of the last month. It allows him to compare his consumption with the previous month and also with an average consumption based on his profile if he completed it.","title":"Description"},{"location":"ecolyo/functionalities/analysis/#graph","text":"On the left side, the user can see his consumption for the konnected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate. Also, when user has the possibility to switch the comparison with the average profile or the ideal profile. For now, the ideal profile just represents the average profile's consumption minus 10%. Each line of the graph is handled by the AnalysisConsumptionRow component. It displays the consumption for a given fluid, a draws a bar sized in comparison with the total and applies the 10% ideal coefficient when user clicks on his ideal consumption. Note that only the consumption related to a connected fluid are taken for the calculation of the total price of the ideal or average consumption, even if the consumption indicators are shown for the non-connected fluids. (it is given a indicator for the user, considering he may use this fluid but doesn't have a connected device)","title":"Graph"},{"location":"ecolyo/functionalities/analysis/#calculation","text":"The Consumption Service allows us to get the user's consumption on the given month, and the Performance Indicator Service allows us to get the comparative indicator between the currently displayed month and the previous one. In order to get the accurate consumption estimation, we use the fluidForecast stored in the user's profile. You can see more about it in the next section : ProfileType","title":"Calculation"},{"location":"ecolyo/functionalities/analysis/#navigation","text":"Users have the possibility to navigate between current and previous analysis, month by month, using the DateNavigator at the top of the screen. It is not possible to navigate after the last analysis (which is set the next month + 3 days in order to have a month with complete data). For example, the 3rd of June, a user will be able to see his analysis of Mai. Users won't be blocked to navigate in previous dates, and if there is no analysis to display, we use the same behavior than in the graph : we display dashes instead of data.","title":"Navigation"},{"location":"ecolyo/functionalities/analysis/#notification","text":"Each month, the user will receive a notification to inform him he can consult his new analysis if he activated it in the option page.","title":"Notification"},{"location":"ecolyo/functionalities/challenge/","text":"This section explain all the functionnalities in the challenge part Quiz A quiz includes 4 basic questions and one custom question. Process Questions and answers are generated in random order. At the begining of the quiz, the user have to select an answer and click validate. Then, he sees the right answer and a modal with the explanation. After this modal, he goes to the next question. Depending on the answer, the question result state is set either to correct or incorrect. If it is a right answer, the quiz result is incremented by one. A user can stop during a quiz and picks up where he left off. To define where the user left off, we have to check if at least one of the question result status is unlocked. Once the custom question is answered, the quiz state is set to done. Then, the user sees his result and his earned stars. He can also retry or go back to the challenge page. Basic Question All basics Questions are created in the quizEntity.json. We have to add : Field Description questionLabel Label of the question answers Array of 3 answers (answerLabel, isTrue) description Explains the question source Source of the explanation Custom Question At the end of every quiz, we're creating a custom question. Here are the fields used to create a custom question Field Type Description type CustomQuestionType Type of custom qusetion: DATE or MAXLOAD or AVERAGE. timeStep TimeStep Time step of the result value (DAY / WEEK / MONTH / YEAR). For MAXLOAD or AVERAGE type, it represents daily / weekly / monthly / yearly average. interval TimeStep Interval in which the data will be searched (DAY / WEEK / MONTH / YEAR) period CustomPeriod Case day / month / year: Use to define a specific period for the interval { day? / month? / year? }. Case weekday: Only usable with AVERAGE type and DAY timestep: Allow to specify a weekday on which average is made. If used with another type, period will not be taken into account. If not assigned the period will be the last interval (example: last week) singleFluid boolean Indicate if all connected fluid should be taken into account. If set to true only the first connected fluid will be taken into account in this order: electricity, gas, water. #unit and #fluid in the question label will be replace by the unit and the name of the fluid result UserQuizState Indicate the state of the custom question (UNLOCKED, CORRECT, UNCORRECT) Calculation of custom question is done by combination of all parameters: Type DATE If period is empty. Retrieve the date of day/month/year (define by timeStep ) from the last week, month, year (define by interval ), if there is no data in this interval, then it will go back to a previous interval, up to a maximum of 6 months example: What day did I consumme the most on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false example: What day did I consumme the most #fluid in #unit on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = true If period is not empty Retrieve the date of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: What month did I consumme the most on year 2020 ? type = CustomQuestionType.DATA timeStep = TimeStep.MONTH interval = TimeStep.YEAR period = { year: 2020 } singleFluid = false Type MAXLOAD If period is empty Retrieve the maxload value of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily max consumption on the last week ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the maxload value of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily max consumption on january 2020 ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false Type AVERAGE If period is empty Retrieve the average of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily average consumption on last week ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the average of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily average consumption on january 2020 ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false If period is weekday Retrieve the average of the weekday from a week, month, year (define by interval ). example: Which is your daily average consumption on wednesdays of last month? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { weekday: 3 } singleFluid = false Wrong answers After defining the right answer, two randows answers are generated depending of the custom question type: type DATE Two dates is generated one, a day before the correct date and the other, a day after. type MAXLOAD or AVERAGE Two random value is generated by applying a coefficient based on the correct answer. This coefficient is randomly included between 0.7 and 0.9 (for the first value) or between 1.1 and 1.3 (for the second value) Exploration Exploration is a feature where the user has to do an action in order to help him discover all features from ecolyo. They are 4 types of actions: DECLARATIVE : The user has to do something outside of the app => No way for the app to know if the user did it so we trust him. ACTION : Action whitin the app. When the user finishes he gets a notification. CONSUMPTION : He has to do something in his consumption view. ECOGESTURE : He needs to look at a specific Ecogesture. In order to check if an exploration (which is not declarative) is done, a hook called useExploration is used.It is called on component that has to check if an exploration is done. This hook called exploration service to check exploration by passing two parameters (the current challenge and the user exploration id associated with the exploration id of the current challenge). This check is done only if: There is a current challenge exploration.id of the current challenge is equal to the user exploration id exploration.state is ONGOING Depends on the type of an exploration, either the exploration remains in progress until it is fully done or it ends. When the user finish the exploration, he gets a success message and five more stars are added to his challenge progression. Action Action is a feature which in the user has to apply an ecogesture for a given duration in order to reduce his consumption. An action refers to the model UserAction in the app, and is an extention of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. UserAction { ecogesture: Ecogesture | null state: UserActionState startDate: DateTime | null } Unlike the exploration, duel and quiz, there is no relationship for an action in the ChallengeEntity model, given that the action is picked by the user. So once it is picked, it is directly stored in the current UserChallenge . When a user launches an action, there is several possible cases : The user has not completed his consumption profile If the user's profile has never been completed, the application will purpose him the default action list which is defined in the action service. The first one of this list will be shown at first, and if the user wants to pick another one, he'll have the choice between the three ecogestures of the default list. The user has completed his consumption profile If the user has completed his profile, the application will purpose him a list of three custom ecogestures. The list is built the following way : First we look for the action that haven't been done yet We pick only the actions that are available for the user's connected fluids We pick the action that are appliable during the current season. At this moment, if the list is smaller than 3, we complete it with actions whose value for property Season is NONE If the list is still smaller than 3 after this, we complete with default actions (This case is rare) Finally, we sort the list of action by efficency and then difficulty. We put the most efficient actions and with the lowest difficulty in first. At any moment of an action, a user can consult his progress through a clock icon and the ending date of his action. The accomplishment of an action is only conditionned by the duration. Once the user completes an action, he'll see a notification on the app and then win his five stars when he comes back to the action screen. Duel On launch In order to find a valid reference period we search for a period which is defined by the duel duration. We check the most recent period first if it's complete and then we go farther and farther in time if the ones before got missing values. We also define a threshold for a maximum old period 6 months for the moment - hard coded. If the thresold is reached and no valid period was found, we alert the user that he can't launch the duel and have to wait before he can retry this process. On going Every time the user goes into the duel mode, we are checking if the duel is finished. if we have retrieved all data to calculate the user consumption on the duel duration, the duel is done. In order to not block the user if a value is mising, we are also setting the duel as done when we reach the startDate + delay in day to retrieve the data (based on the fluid) + 1 day. In this case the user consumption is done on known values. On finish Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge. Challenges We can find the file challengeEntity.json in the /db folder. This file contains an array of challenges, and each of them includes relationships to duels, quiz, missions and actions. For more precision about the data managment system you can refer the picture in the Initialization section","title":"Challenge"},{"location":"ecolyo/functionalities/challenge/#quiz","text":"A quiz includes 4 basic questions and one custom question.","title":"Quiz"},{"location":"ecolyo/functionalities/challenge/#process","text":"Questions and answers are generated in random order. At the begining of the quiz, the user have to select an answer and click validate. Then, he sees the right answer and a modal with the explanation. After this modal, he goes to the next question. Depending on the answer, the question result state is set either to correct or incorrect. If it is a right answer, the quiz result is incremented by one. A user can stop during a quiz and picks up where he left off. To define where the user left off, we have to check if at least one of the question result status is unlocked. Once the custom question is answered, the quiz state is set to done. Then, the user sees his result and his earned stars. He can also retry or go back to the challenge page.","title":"Process"},{"location":"ecolyo/functionalities/challenge/#basic-question","text":"All basics Questions are created in the quizEntity.json. We have to add : Field Description questionLabel Label of the question answers Array of 3 answers (answerLabel, isTrue) description Explains the question source Source of the explanation","title":"Basic Question"},{"location":"ecolyo/functionalities/challenge/#custom-question","text":"At the end of every quiz, we're creating a custom question. Here are the fields used to create a custom question Field Type Description type CustomQuestionType Type of custom qusetion: DATE or MAXLOAD or AVERAGE. timeStep TimeStep Time step of the result value (DAY / WEEK / MONTH / YEAR). For MAXLOAD or AVERAGE type, it represents daily / weekly / monthly / yearly average. interval TimeStep Interval in which the data will be searched (DAY / WEEK / MONTH / YEAR) period CustomPeriod Case day / month / year: Use to define a specific period for the interval { day? / month? / year? }. Case weekday: Only usable with AVERAGE type and DAY timestep: Allow to specify a weekday on which average is made. If used with another type, period will not be taken into account. If not assigned the period will be the last interval (example: last week) singleFluid boolean Indicate if all connected fluid should be taken into account. If set to true only the first connected fluid will be taken into account in this order: electricity, gas, water. #unit and #fluid in the question label will be replace by the unit and the name of the fluid result UserQuizState Indicate the state of the custom question (UNLOCKED, CORRECT, UNCORRECT) Calculation of custom question is done by combination of all parameters:","title":"Custom Question"},{"location":"ecolyo/functionalities/challenge/#type-date","text":"If period is empty. Retrieve the date of day/month/year (define by timeStep ) from the last week, month, year (define by interval ), if there is no data in this interval, then it will go back to a previous interval, up to a maximum of 6 months example: What day did I consumme the most on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false example: What day did I consumme the most #fluid in #unit on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = true If period is not empty Retrieve the date of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: What month did I consumme the most on year 2020 ? type = CustomQuestionType.DATA timeStep = TimeStep.MONTH interval = TimeStep.YEAR period = { year: 2020 } singleFluid = false","title":"Type DATE"},{"location":"ecolyo/functionalities/challenge/#type-maxload","text":"If period is empty Retrieve the maxload value of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily max consumption on the last week ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the maxload value of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily max consumption on january 2020 ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false","title":"Type MAXLOAD"},{"location":"ecolyo/functionalities/challenge/#type-average","text":"If period is empty Retrieve the average of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily average consumption on last week ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the average of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily average consumption on january 2020 ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false If period is weekday Retrieve the average of the weekday from a week, month, year (define by interval ). example: Which is your daily average consumption on wednesdays of last month? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { weekday: 3 } singleFluid = false","title":"Type AVERAGE"},{"location":"ecolyo/functionalities/challenge/#wrong-answers","text":"After defining the right answer, two randows answers are generated depending of the custom question type: type DATE Two dates is generated one, a day before the correct date and the other, a day after. type MAXLOAD or AVERAGE Two random value is generated by applying a coefficient based on the correct answer. This coefficient is randomly included between 0.7 and 0.9 (for the first value) or between 1.1 and 1.3 (for the second value)","title":"Wrong answers"},{"location":"ecolyo/functionalities/challenge/#exploration","text":"Exploration is a feature where the user has to do an action in order to help him discover all features from ecolyo. They are 4 types of actions: DECLARATIVE : The user has to do something outside of the app => No way for the app to know if the user did it so we trust him. ACTION : Action whitin the app. When the user finishes he gets a notification. CONSUMPTION : He has to do something in his consumption view. ECOGESTURE : He needs to look at a specific Ecogesture. In order to check if an exploration (which is not declarative) is done, a hook called useExploration is used.It is called on component that has to check if an exploration is done. This hook called exploration service to check exploration by passing two parameters (the current challenge and the user exploration id associated with the exploration id of the current challenge). This check is done only if: There is a current challenge exploration.id of the current challenge is equal to the user exploration id exploration.state is ONGOING Depends on the type of an exploration, either the exploration remains in progress until it is fully done or it ends. When the user finish the exploration, he gets a success message and five more stars are added to his challenge progression.","title":"Exploration"},{"location":"ecolyo/functionalities/challenge/#action","text":"Action is a feature which in the user has to apply an ecogesture for a given duration in order to reduce his consumption. An action refers to the model UserAction in the app, and is an extention of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. UserAction { ecogesture: Ecogesture | null state: UserActionState startDate: DateTime | null } Unlike the exploration, duel and quiz, there is no relationship for an action in the ChallengeEntity model, given that the action is picked by the user. So once it is picked, it is directly stored in the current UserChallenge . When a user launches an action, there is several possible cases :","title":"Action"},{"location":"ecolyo/functionalities/challenge/#the-user-has-not-completed-his-consumption-profile","text":"If the user's profile has never been completed, the application will purpose him the default action list which is defined in the action service. The first one of this list will be shown at first, and if the user wants to pick another one, he'll have the choice between the three ecogestures of the default list.","title":"The user has not completed his consumption profile"},{"location":"ecolyo/functionalities/challenge/#the-user-has-completed-his-consumption-profile","text":"If the user has completed his profile, the application will purpose him a list of three custom ecogestures. The list is built the following way : First we look for the action that haven't been done yet We pick only the actions that are available for the user's connected fluids We pick the action that are appliable during the current season. At this moment, if the list is smaller than 3, we complete it with actions whose value for property Season is NONE If the list is still smaller than 3 after this, we complete with default actions (This case is rare) Finally, we sort the list of action by efficency and then difficulty. We put the most efficient actions and with the lowest difficulty in first. At any moment of an action, a user can consult his progress through a clock icon and the ending date of his action. The accomplishment of an action is only conditionned by the duration. Once the user completes an action, he'll see a notification on the app and then win his five stars when he comes back to the action screen.","title":"The user has completed his consumption profile"},{"location":"ecolyo/functionalities/challenge/#duel","text":"","title":"Duel"},{"location":"ecolyo/functionalities/challenge/#on-launch","text":"In order to find a valid reference period we search for a period which is defined by the duel duration. We check the most recent period first if it's complete and then we go farther and farther in time if the ones before got missing values. We also define a threshold for a maximum old period 6 months for the moment - hard coded. If the thresold is reached and no valid period was found, we alert the user that he can't launch the duel and have to wait before he can retry this process.","title":"On launch"},{"location":"ecolyo/functionalities/challenge/#on-going","text":"Every time the user goes into the duel mode, we are checking if the duel is finished. if we have retrieved all data to calculate the user consumption on the duel duration, the duel is done. In order to not block the user if a value is mising, we are also setting the duel as done when we reach the startDate + delay in day to retrieve the data (based on the fluid) + 1 day. In this case the user consumption is done on known values.","title":"On going"},{"location":"ecolyo/functionalities/challenge/#on-finish","text":"Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge.","title":"On finish"},{"location":"ecolyo/functionalities/challenge/#challenges","text":"We can find the file challengeEntity.json in the /db folder. This file contains an array of challenges, and each of them includes relationships to duels, quiz, missions and actions. For more precision about the data managment system you can refer the picture in the Initialization section","title":"Challenges"},{"location":"ecolyo/functionalities/consumption/","text":"Consumption Ecolyo allow user to see its consumption in two way: globally with the Mutlifluid view that displays euro consumptions more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu All consumption information are retrieved and calculated by services from the application. Time step Different time steps can be selected by the user which will display different period on the graph according to the time step. Day: display data at half-an-hour step on a period of one day Week: display data at daily step on a period of a week Month: display data at daily step on a period of a month Year: display data at monthly step on a period of a year 5 years: display data at yearly step on a period of 5 years (5 last years) Data Interval For each fluid, we have an upcoming data interval depending on the energy provider API's. When we check the data, we display directly the data or a specific message according to the last data we have in comparison with the actual date and the last data date. We rely on these 3 intervals to show different messages : For Enedis, the interval is 3 days For GRDF, the interval is 5 days For EGL, the interval is 5 days ConsumptionView Description This view is the main view of the application. It displays an agreggation view of all connected fluids. It is the entrypoint to several children components that each handles a particular feature : DateNavigator FluidButtons FluidChart ConsumptionDetails KonnectorViewerList / KonnectorViewerCard The submenu (FluidButtons), allows the user to switch between the different fluids and the multifluid view. Rules If no fluids are connected, this view will display the multifluid view with the KonnectorViewerList component which shows buttons that allow user to connect its first fluids. These buttons redirects to the chosen fluid section with the connection form. If at least one fluid is connected, the multi fluid view and the connected fluids views are shown (electricity, water, gas). For the multifluid view, Fluids are displayed in multi fluid color and in euro Fluid is displayed in the given fluid color and unit (kWh for electricity and gaz, l for water) TimeStep available are the following: week, month, year, 5 years and day for electricity fluid If user has selected day time step and change the fluid, the week time step will be selected by default. DateNavigator Description The component allows the user to navigate through the selected timestep (week by week, month by month, etc.) Rules If no fluid is connected, the navigation is locked By default, the date is set to the lastDataDate. Navigation is locked above the current date. FluidButtons Description The component allows the user to navigate through the different fluid views (multifluid, electricity, water, gaz) Rules If a Konnector is errored or its data is outdated, we show a red cross on the fluid icon If the fluid is not connected we show a \"turn on\" icon Icons have an active state. (They are coloured when selected) FluidChart Description This component is the one that shows the user its consumption, according to the selected fluid, timestep and date. It is splitted in 3 distinct parts: The ConsumptionVisualier The FluidSlides The TimeStep Navigator Rules Component Rules ConsumptionVisualizer Calls the DataloadConsumptionVisualizer component that shows the dataload of the selected timeStep and fluid For multifluid, we show the total consumption of all connected fluid, and the consumption fluid by fluid, all in \u20ac We display a message according to the data state as explained in the DataLoad Consumption Visualizer FluidSlides This component calls the fluidSwipe component which is handled by the library react-swipeable-views , and allows the user to swipe accross the selected timestep. This library loads the slides before and after the current slide, so we reduce the loading time between slides. TimeStepSelector This component allows the user to change the current Timestep, or to return to today's date with a button DataLoad Consumption Visualizer Description This view displays the load of a specified fluid (electricity, water, gas) or the total consumption on the multifluid screen. The display will be done in function of the data state. Rules to define data state The data state is define in the \"ConsumptionFormatter\" service following theses rules : For single fluid Condition State Before the first data available EMPTY Between the first and last data available & value of load is not empty VALID Between the first and last data available & value of load is empty HOLE After the last data available & Before today & in the dataDelayOffset period UPCOMING After the last data available & Before today & not in the dataDelayOffset period MISSING After today COMING For multifluid Condition State All fluids have empty data AGGREGATED_EMPTY At least one fluid have a data and another fluids with empty data AGGREGATED_WITH_EMPTY All fluids have valid data AGGREGATED_VALID All fluid have a hole or missing data AGGREGATED_HOLE_OR_MISSING At least one fluid have a data and another fluids with a missing or hole data AGGREGATED_WITH_HOLE_OR_MISSING At least one fluid have upcoming or coming data and other fluid doesn\u2019t have missing or hole data AGGREGATED_WITH_COMING All fluid have coming data AGGREGATED_COMING Display of the specific cases (component: DataloadNoValue) This display appear instead of the traditionnal one (described below). It is used to display a general message which override the value. Here are the rules : Condition Displayed label Comments Single fluid && dataload state = EMPTY Pas de donn\u00e9es Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pas de donn\u00e9es Single fluid && dataload state = MISSING Donn\u00e9es manquantes Displayed in red and clickable (scroll to the konnector card) Single fluid && dataload state = UPCOMING \u00c0 venir Single fluid && dataload state = COMING \u00c0 venir Multi fluid && dataload state = AGGREGATED_EMPTY Pas de donn\u00e9es Multi fluid && dataload state = AGGREGATED_WITH_EMPTY - Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Donn\u00e9es manquantes Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING - Multi fluid && dataload state = AGGREGATED_COMING \u00c0 venir Display of the load values In function of the fluid type (single or multi) and of the data state, the display will be adapted. Display of the main value (component: DataloadSectionValue) Used to display the load or price in function of following rules : Condition Displayed information Single fluid && dataload value < 1000 Display the load Single fluid && dataload value >= 1000 Display the load in Mega unit Multifluid without comparison Display the load converted in euro and a link to display the Estimated Modal information Multifluid with comparison Display the load converted in euro Display of the detail value (component: DataloadSectionDetail) Used to display the detail just below the main value. The information displayed are : Condition Displayed information Single fluid Display the load converted in euro Multifluid without comparison Display the load converted in euro for each available fluid Multifluid with comparison Display nothing Information (component: InfoDataConsumptionVisualizer) In addition of the value / load / message displayed, we can displayed an additionnal information. Condition Displayed label Comments Single fluid && dataload state = EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = MISSING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = UPCOMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = COMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Multi fluid && dataload state = AGGREGATED_EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_COMING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Comparison The user can compare its data with a previous period using a switch which will display the previous period on the same chart. The chart scale will adapt to the max load displayed between the actualData and the comparisonData Konnector Viewer Card This component shows the konnector's state and allows the user to connect, delete, or update a konnector Rules If the fluid is konnected, this component will shows the konnector state at the end of the consumption page If the fluid is not konnected, it will show the connection form If the konnector is in error or its data is outdated, it will display the number of days since the data is outdated If the error is a login error (eg: user consent is revocated), it will show a specific message If the data is outdated but the user has already triggered an update today, we will show a message that informs the user that the issue is probably related to the energy provider","title":"Consumption"},{"location":"ecolyo/functionalities/consumption/#consumption","text":"Ecolyo allow user to see its consumption in two way: globally with the Mutlifluid view that displays euro consumptions more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu All consumption information are retrieved and calculated by services from the application.","title":"Consumption"},{"location":"ecolyo/functionalities/consumption/#time-step","text":"Different time steps can be selected by the user which will display different period on the graph according to the time step. Day: display data at half-an-hour step on a period of one day Week: display data at daily step on a period of a week Month: display data at daily step on a period of a month Year: display data at monthly step on a period of a year 5 years: display data at yearly step on a period of 5 years (5 last years)","title":"Time step"},{"location":"ecolyo/functionalities/consumption/#data-interval","text":"For each fluid, we have an upcoming data interval depending on the energy provider API's. When we check the data, we display directly the data or a specific message according to the last data we have in comparison with the actual date and the last data date. We rely on these 3 intervals to show different messages : For Enedis, the interval is 3 days For GRDF, the interval is 5 days For EGL, the interval is 5 days","title":"Data Interval"},{"location":"ecolyo/functionalities/consumption/#consumptionview","text":"","title":"ConsumptionView"},{"location":"ecolyo/functionalities/consumption/#description","text":"This view is the main view of the application. It displays an agreggation view of all connected fluids. It is the entrypoint to several children components that each handles a particular feature : DateNavigator FluidButtons FluidChart ConsumptionDetails KonnectorViewerList / KonnectorViewerCard The submenu (FluidButtons), allows the user to switch between the different fluids and the multifluid view.","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules","text":"If no fluids are connected, this view will display the multifluid view with the KonnectorViewerList component which shows buttons that allow user to connect its first fluids. These buttons redirects to the chosen fluid section with the connection form. If at least one fluid is connected, the multi fluid view and the connected fluids views are shown (electricity, water, gas). For the multifluid view, Fluids are displayed in multi fluid color and in euro Fluid is displayed in the given fluid color and unit (kWh for electricity and gaz, l for water) TimeStep available are the following: week, month, year, 5 years and day for electricity fluid If user has selected day time step and change the fluid, the week time step will be selected by default.","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#datenavigator","text":"","title":"DateNavigator"},{"location":"ecolyo/functionalities/consumption/#description_1","text":"The component allows the user to navigate through the selected timestep (week by week, month by month, etc.)","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_1","text":"If no fluid is connected, the navigation is locked By default, the date is set to the lastDataDate. Navigation is locked above the current date.","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#fluidbuttons","text":"","title":"FluidButtons"},{"location":"ecolyo/functionalities/consumption/#description_2","text":"The component allows the user to navigate through the different fluid views (multifluid, electricity, water, gaz)","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_2","text":"If a Konnector is errored or its data is outdated, we show a red cross on the fluid icon If the fluid is not connected we show a \"turn on\" icon Icons have an active state. (They are coloured when selected)","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#fluidchart","text":"","title":"FluidChart"},{"location":"ecolyo/functionalities/consumption/#description_3","text":"This component is the one that shows the user its consumption, according to the selected fluid, timestep and date. It is splitted in 3 distinct parts: The ConsumptionVisualier The FluidSlides The TimeStep Navigator","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_3","text":"Component Rules ConsumptionVisualizer Calls the DataloadConsumptionVisualizer component that shows the dataload of the selected timeStep and fluid For multifluid, we show the total consumption of all connected fluid, and the consumption fluid by fluid, all in \u20ac We display a message according to the data state as explained in the DataLoad Consumption Visualizer FluidSlides This component calls the fluidSwipe component which is handled by the library react-swipeable-views , and allows the user to swipe accross the selected timestep. This library loads the slides before and after the current slide, so we reduce the loading time between slides. TimeStepSelector This component allows the user to change the current Timestep, or to return to today's date with a button","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#dataload-consumption-visualizer","text":"","title":"DataLoad Consumption Visualizer"},{"location":"ecolyo/functionalities/consumption/#description_4","text":"This view displays the load of a specified fluid (electricity, water, gas) or the total consumption on the multifluid screen. The display will be done in function of the data state.","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules-to-define-data-state","text":"The data state is define in the \"ConsumptionFormatter\" service following theses rules :","title":"Rules to define data state"},{"location":"ecolyo/functionalities/consumption/#for-single-fluid","text":"Condition State Before the first data available EMPTY Between the first and last data available & value of load is not empty VALID Between the first and last data available & value of load is empty HOLE After the last data available & Before today & in the dataDelayOffset period UPCOMING After the last data available & Before today & not in the dataDelayOffset period MISSING After today COMING","title":"For single fluid"},{"location":"ecolyo/functionalities/consumption/#for-multifluid","text":"Condition State All fluids have empty data AGGREGATED_EMPTY At least one fluid have a data and another fluids with empty data AGGREGATED_WITH_EMPTY All fluids have valid data AGGREGATED_VALID All fluid have a hole or missing data AGGREGATED_HOLE_OR_MISSING At least one fluid have a data and another fluids with a missing or hole data AGGREGATED_WITH_HOLE_OR_MISSING At least one fluid have upcoming or coming data and other fluid doesn\u2019t have missing or hole data AGGREGATED_WITH_COMING All fluid have coming data AGGREGATED_COMING","title":"For multifluid"},{"location":"ecolyo/functionalities/consumption/#display-of-the-specific-cases-component-dataloadnovalue","text":"This display appear instead of the traditionnal one (described below). It is used to display a general message which override the value. Here are the rules : Condition Displayed label Comments Single fluid && dataload state = EMPTY Pas de donn\u00e9es Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pas de donn\u00e9es Single fluid && dataload state = MISSING Donn\u00e9es manquantes Displayed in red and clickable (scroll to the konnector card) Single fluid && dataload state = UPCOMING \u00c0 venir Single fluid && dataload state = COMING \u00c0 venir Multi fluid && dataload state = AGGREGATED_EMPTY Pas de donn\u00e9es Multi fluid && dataload state = AGGREGATED_WITH_EMPTY - Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Donn\u00e9es manquantes Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING - Multi fluid && dataload state = AGGREGATED_COMING \u00c0 venir","title":"Display of the specific cases (component: DataloadNoValue)"},{"location":"ecolyo/functionalities/consumption/#display-of-the-load-values","text":"In function of the fluid type (single or multi) and of the data state, the display will be adapted.","title":"Display of the load values"},{"location":"ecolyo/functionalities/consumption/#display-of-the-main-value-component-dataloadsectionvalue","text":"Used to display the load or price in function of following rules : Condition Displayed information Single fluid && dataload value < 1000 Display the load Single fluid && dataload value >= 1000 Display the load in Mega unit Multifluid without comparison Display the load converted in euro and a link to display the Estimated Modal information Multifluid with comparison Display the load converted in euro","title":"Display of the main value (component: DataloadSectionValue)"},{"location":"ecolyo/functionalities/consumption/#display-of-the-detail-value-component-dataloadsectiondetail","text":"Used to display the detail just below the main value. The information displayed are : Condition Displayed information Single fluid Display the load converted in euro Multifluid without comparison Display the load converted in euro for each available fluid Multifluid with comparison Display nothing","title":"Display of the detail value (component: DataloadSectionDetail)"},{"location":"ecolyo/functionalities/consumption/#information-component-infodataconsumptionvisualizer","text":"In addition of the value / load / message displayed, we can displayed an additionnal information. Condition Displayed label Comments Single fluid && dataload state = EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = MISSING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = UPCOMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = COMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Multi fluid && dataload state = AGGREGATED_EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_COMING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX","title":"Information (component: InfoDataConsumptionVisualizer)"},{"location":"ecolyo/functionalities/consumption/#comparison","text":"The user can compare its data with a previous period using a switch which will display the previous period on the same chart. The chart scale will adapt to the max load displayed between the actualData and the comparisonData","title":"Comparison"},{"location":"ecolyo/functionalities/consumption/#konnector-viewer-card","text":"This component shows the konnector's state and allows the user to connect, delete, or update a konnector","title":"Konnector Viewer Card"},{"location":"ecolyo/functionalities/consumption/#rules_4","text":"If the fluid is konnected, this component will shows the konnector state at the end of the consumption page If the fluid is not konnected, it will show the connection form If the konnector is in error or its data is outdated, it will display the number of days since the data is outdated If the error is a login error (eg: user consent is revocated), it will show a specific message If the data is outdated but the user has already triggered an update today, we will show a message that informs the user that the issue is probably related to the energy provider","title":"Rules"},{"location":"ecolyo/functionalities/dacc/","text":"DACC What is DACC ? A cozy blackbox where apps can send data in order to be anonymised and aggregate to provide usage stats. Infrastructure workflow We have two environements, a dev one and a production. Both of them look like the following schema : On the developpement env, the 'cozy env' refers to our 'Alpha' VM. Service There is a service named aggregatorUsageEvent , running on a daily basis, sending pre-processed data to cozy. This service is responsible for parsing traced events store in database and send them to cozy. The service is configured to run every night at 01:00AM . Usage events This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Title Tech name target context startDate result trigger Cozy Dacc Name Changement d'action dans un challenge ActionChangeEvent Id de l'action Id du challenge en cours --- --- Chaque appui sur le bouton selectEcogesture dans le ActionCard navigation-action-daily Validation de la fin d'une action ActionEndEvent Id de l'ecogeste Id du challenge en cours Date de d\u00e9but de l'action --- Lors de l'appui sur le bouton de fin d'action event-duration Connexion d'un utilisateur ConnectionEvent --- Navigateur utilis\u00e9 --- Si c'est la premi\u00e8re connexion firstConnection est stock\u00e9 A chaque chargement de l'application connection-count-daily Connecteur Classique KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' en cas d'erreur de quelque type que ce soit (catch) konnector-event-daily Connecteur Oauth (enedis, GRDF) KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' dans le cas ou aucun accoun n'est cr\u00e9\u00e9 konnector-event-daily Refresh manuel du connecteur KonnectorRefreshEvent Slug du connecteur --- --- Success ou error. Le succ\u00e8s est set quand l'\u00e9tat du trigger est a 'done' Lors de l'appuie sur le bouton 'mettre a jour' konnector-event-daily Navigation utilisateur dans l'application NavigationEvent Nom de la page ( voir 1. en dessous ) --- --- --- --- navigation-count-daily Comparaison de consomation ConsumptionCompareEvent timestep in lowercase fluid type in lowercase --- --- --- navigation-action-daily Changement de pas de temps ConsumptionChangeTimeStepEvent timestep in lowercase fluid type --- --- --- navigation-action-daily Lancement d'un challenge ChallengeLaunchEvent challenge id --- --- --- Appuie sur le bouton de lancement de challenge dans le cas on la pop-up 'pas de fluid' ne s'affiche pas event-duration Title Tech name target context startDate result trigger Cozy Dacc Name Fin d'un challenge ChallengeEndEvent challenge id --- date de d\u00e9but du challenge --- Lors de la visualisation d'un challenge, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration D\u00e9but d'un duel DuelLaunchEvent duel id challenge id --- --- Appuie sur le bouton de lancement d'un duel event-duration Fin d'un duel DuelEndEvent duel id --- challenge start date 'win' or 'loss' Lors de la visualisation d'un duel, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration Fin d'un quiz QuizEndEvent Quiz id Challenge Id Quiz start date Resultat du quiz (de 0 a 5) Lors de la pop-up de r\u00e9sultat event-duration Fin d'une exploration ExplorationEndEvent exploration id challenge id exploration start date --- Lors de la pop-up de r\u00e9sultat event-duration Changement de choix d'action ActionChangeEvent action id current challenge id --- --- Lors du click sur le bouton d'acceptation de l'action navigation-action-daily Fin d'une action ActionEndEvent action id current challenge id action start date --- Lors du click sur le bouton de validation de la page ActionDone event-duration Compl\u00e9tion d'un nouveau profile ProfileSetEvent --- --- --- --- Lors de l'affichage de la page de f\u00e9licitation profileTypeFinished navigation-action-daily Consultation du nouveau bilan mensuel ReportFromEvent --- 'analysis' --- 1 Lorsque l'utilisateur consulte sa page analyse quand la notification est activ\u00e9e summary-subscription-monthly Tentatitve de connexion \u00e0 un connecteur (initialisation) KonnectorAttemptEvent Slug du connecteur --- --- 'success or error' Lorsque l'utilisateur clique sur le bouton de connexion. Lorsque la connexion est r\u00e9ussie, et que l'utilisateur clique sur OK dans la modale le result est pass\u00e9 \u00e0 'success' konnector-attempts-monthly Nom de la page, diff\u00e9rents cas existant Page target Trigger Consomation 'electricity', 'gas', 'eau', 'multifluid' Click sur un des fluids dans la bar navigation FAQ 'faq' Click sur la card de consultation CGU 'legalNotice' Click sur la card de Legal Notice Autres 'consumption' 'challenges' 'ecogestures' 'analysis' 'options' Click dans la navbar Indicators note All indicators are only sent if a user validate first version of CGU, the one containing dacc validation Monthly Indicators All monthly indicators call can be found after this comment on the code // Monthly events Indicator Trigger value consumption-variation-monthly Tous les mois si l'utilisateur a \u00e9t\u00e9 connect\u00e9 au moins une fois dans le mois La variation de consomation par type de fluide. Les param\u00e8tres diff\u00e9rents sont le type de profil ainsi que le nombre de mois entre la premi\u00e8re connexion de l'utilisateur et le moment o\u00f9 est remont\u00e9 l'indicateur (seniority) summary-subscription-monthly Tous les mois si un utilisateur a souscrit a la newsletter ou c'est d\u00e9sabonn\u00e9 1 si l'utilsteur est inscrit sinon 0 fluid-data-granularity-monthly Tous les mois sans condition 1 si l'utilisateur poss\u00e8de de la donn\u00e9e a la demi heure sur le mois. Sinon 0 connection-count-monthly Tous les mois si il y a eu au moins une connexion Le nombre de jour unique de connexion profile-count-monthly Tous les mois si le profil a \u00e9t\u00e9 compl\u00e9t\u00e9 au moins une fois Le nombre de fois ou le profile a \u00e9t\u00e9 compl\u00e9t\u00e9 konnector-attempts-monthly Tous les mois, le nombre de tentative de connexion pour connecter un connecteur la premi\u00e8re fois. Une fois la connexion r\u00e9ussie, l'indicateur remonte 1 dans le groupe \"success\". L'indicateur ne remonte ensuite plus pour cet utilisateur car il aura d\u00e9j\u00e0 r\u00e9ussi \u00e0 se connecter une premi\u00e8re fois. Le nombre total de tentatives Daily Indicators The daily process get all events of previous day and process them in the following indicators Indicator Trigger value connection-count-daily Tous les jours Nombre de connexion. Celle-ci sont cat\u00e9goris\u00e9 par type (mobile ou desktop), bas\u00e9 sur le navigateur de l'utilisateur. (les tablettes sont compt\u00e9es comme des mobiles) konnector-event-daily Tous les jours Nombre d'essai. Ils sont cat\u00e9goris\u00e9 par type de connecteur, refresh/success et le status (error ou success) konnector-connected-daily Tous les jours La valeur est 1. Les valeurs sont cat\u00e9goris\u00e9es par type de fluide (electricity / electricity:water ...) navigation-count-daily Tous les jours nombre de page visualis\u00e9 par type de page challenge-launch-daily Tous les jours Nombre de d\u00e9fis lanc\u00e9s lors d'un challenge session-duration Tous les jours Dur\u00e9e de la session en secondes navigation-action-daily Tous les jours Nombre d'action sur une page donn\u00e9e. Exemple sur la consomation on trace les changements de pas de temps sur chaque graph. event-duration Tous les jours Dur\u00e9e entre deux \u00e9v\u00e9nements: 1ere session et premier challenge / d\u00e9but de challenge et fin de challenge / d\u00e9but d'exploration et fin d'exploration / d\u00e9but d'action et fin d'action / d\u00e9but de duel et fin de duel quiz-stars Tous les jours Nombre d'\u00e9toiles obtenu a la fin d'un quiz Information sending Format All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. The structure to send is the following : { createdBy: string measureName: string startDate: string value: number | null group1?: object group2?: object group3?: object } with: createdBy : contains \"ecolyo\" value. startDate : used to defined the start date of the indicator value : contains a value relevant to the defined indicator (example: number of page viewed on a day). groups : contains all attributes defining a indicator. Please refer to indicators definition (https://stats.cozycloud.cc/question#eyJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjo0LCJxdWVyeSI6eyJzb3VyY2UtdGFibGUiOjh9LCJ0eXBlIjoicXVlcnkifSwiZGlzcGxheSI6InRhYmxlIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319) mesureName : contains one of the following value ENUM value CONNECTION_COUNT_DAILY connection-count-daily KONNECTOR_EVENT_DAILY konnector-event-daily KONNECTOR_CONNECTED_PER_DAY konnector-connected-daily NAVIGATION_COUNT_DAILY navigation-count-daily CHALLENGE_LAUNCH_EVENT_DAILY challenge-launch-daily CONSUMPTION_VARIATION_MONTHLY consumption-variation-monthly SESSION_DURATION session-duration NAVIGATION_ACTION_DAILY navigation-action-daily EVENT_DURATION event-duration QUIZ_STARS quiz-stars SUMMARY_SUBSCRIPTION_MONTHLY summary-subscription-monthly FLUID_DATA_GRANULARITY fluid-data-granularity-monthly CONNECTION_COUNT_MONTHLY connection-count-monthly PROFILE_COUNT_MONTHLY profile-count-monthly KONNECTOR_ATTEMPTS_MONTHLY konnector-attempts-monthly Environnements There is two remote doctypes pointing to two differents mode. dacc-dev is used on alpha. \"dacc\" : { \"type\" : \"cc.cozycloud.dacc\" , \"verbs\" : [ \"ALL\" ] }, \"dacc-dev\" : { \"type\" : \"cc.cozycloud.dacc.dev\" , \"verbs\" : [ \"ALL\" ] }, How to local test ? First you need to modify the service in order to be able to see data in local : Modify dacc URL in order to see data (ligne 67) await client . getStackClient () . fetchJSON ( 'POST' , environementService . isProduction () ? 'http://localhost:8081' : '/remote/cc.cozycloud.dacc.dev' , { data : JSON . stringify ( indicator ), } ) Remove date protection if you want to test monthly indicators (ligne 1100) if ( profile // && // DateTime.local() // .setZone('utc', { // keepLocalTime: true, // }) // .startOf('day').day === profile.monthlyAnalysisDate.day ) { Then you need to launch a script that will simulate dacc api's. This terminal will listen to incoming request cd ./scripts node server.js Then you are finaly ready to test ! Just run the following : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\a ggregatorUsageEvents \\e colyo.js You must see sent indicators in the previously open terminal { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } How to add new indicator ? You have to reach cozy and discuss with them about new indicators. They will implement it for dacc-dev and dacc and you will be able to test it on alpha env. Remember you will need at least 5 data of each type to see it in metabase. Visualisation All the data aggregated in the dacc can be visualized with a Metabase website hosted by cozy (https://stats.cozycloud.cc/).","title":"Dacc"},{"location":"ecolyo/functionalities/dacc/#dacc","text":"What is DACC ? A cozy blackbox where apps can send data in order to be anonymised and aggregate to provide usage stats.","title":"DACC"},{"location":"ecolyo/functionalities/dacc/#infrastructure-workflow","text":"We have two environements, a dev one and a production. Both of them look like the following schema : On the developpement env, the 'cozy env' refers to our 'Alpha' VM.","title":"Infrastructure workflow"},{"location":"ecolyo/functionalities/dacc/#service","text":"There is a service named aggregatorUsageEvent , running on a daily basis, sending pre-processed data to cozy. This service is responsible for parsing traced events store in database and send them to cozy. The service is configured to run every night at 01:00AM .","title":"Service"},{"location":"ecolyo/functionalities/dacc/#usage-events","text":"This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Title Tech name target context startDate result trigger Cozy Dacc Name Changement d'action dans un challenge ActionChangeEvent Id de l'action Id du challenge en cours --- --- Chaque appui sur le bouton selectEcogesture dans le ActionCard navigation-action-daily Validation de la fin d'une action ActionEndEvent Id de l'ecogeste Id du challenge en cours Date de d\u00e9but de l'action --- Lors de l'appui sur le bouton de fin d'action event-duration Connexion d'un utilisateur ConnectionEvent --- Navigateur utilis\u00e9 --- Si c'est la premi\u00e8re connexion firstConnection est stock\u00e9 A chaque chargement de l'application connection-count-daily Connecteur Classique KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' en cas d'erreur de quelque type que ce soit (catch) konnector-event-daily Connecteur Oauth (enedis, GRDF) KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' dans le cas ou aucun accoun n'est cr\u00e9\u00e9 konnector-event-daily Refresh manuel du connecteur KonnectorRefreshEvent Slug du connecteur --- --- Success ou error. Le succ\u00e8s est set quand l'\u00e9tat du trigger est a 'done' Lors de l'appuie sur le bouton 'mettre a jour' konnector-event-daily Navigation utilisateur dans l'application NavigationEvent Nom de la page ( voir 1. en dessous ) --- --- --- --- navigation-count-daily Comparaison de consomation ConsumptionCompareEvent timestep in lowercase fluid type in lowercase --- --- --- navigation-action-daily Changement de pas de temps ConsumptionChangeTimeStepEvent timestep in lowercase fluid type --- --- --- navigation-action-daily Lancement d'un challenge ChallengeLaunchEvent challenge id --- --- --- Appuie sur le bouton de lancement de challenge dans le cas on la pop-up 'pas de fluid' ne s'affiche pas event-duration Title Tech name target context startDate result trigger Cozy Dacc Name Fin d'un challenge ChallengeEndEvent challenge id --- date de d\u00e9but du challenge --- Lors de la visualisation d'un challenge, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration D\u00e9but d'un duel DuelLaunchEvent duel id challenge id --- --- Appuie sur le bouton de lancement d'un duel event-duration Fin d'un duel DuelEndEvent duel id --- challenge start date 'win' or 'loss' Lors de la visualisation d'un duel, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration Fin d'un quiz QuizEndEvent Quiz id Challenge Id Quiz start date Resultat du quiz (de 0 a 5) Lors de la pop-up de r\u00e9sultat event-duration Fin d'une exploration ExplorationEndEvent exploration id challenge id exploration start date --- Lors de la pop-up de r\u00e9sultat event-duration Changement de choix d'action ActionChangeEvent action id current challenge id --- --- Lors du click sur le bouton d'acceptation de l'action navigation-action-daily Fin d'une action ActionEndEvent action id current challenge id action start date --- Lors du click sur le bouton de validation de la page ActionDone event-duration Compl\u00e9tion d'un nouveau profile ProfileSetEvent --- --- --- --- Lors de l'affichage de la page de f\u00e9licitation profileTypeFinished navigation-action-daily Consultation du nouveau bilan mensuel ReportFromEvent --- 'analysis' --- 1 Lorsque l'utilisateur consulte sa page analyse quand la notification est activ\u00e9e summary-subscription-monthly Tentatitve de connexion \u00e0 un connecteur (initialisation) KonnectorAttemptEvent Slug du connecteur --- --- 'success or error' Lorsque l'utilisateur clique sur le bouton de connexion. Lorsque la connexion est r\u00e9ussie, et que l'utilisateur clique sur OK dans la modale le result est pass\u00e9 \u00e0 'success' konnector-attempts-monthly Nom de la page, diff\u00e9rents cas existant Page target Trigger Consomation 'electricity', 'gas', 'eau', 'multifluid' Click sur un des fluids dans la bar navigation FAQ 'faq' Click sur la card de consultation CGU 'legalNotice' Click sur la card de Legal Notice Autres 'consumption' 'challenges' 'ecogestures' 'analysis' 'options' Click dans la navbar","title":"Usage events"},{"location":"ecolyo/functionalities/dacc/#indicators","text":"note All indicators are only sent if a user validate first version of CGU, the one containing dacc validation","title":"Indicators"},{"location":"ecolyo/functionalities/dacc/#monthly-indicators","text":"All monthly indicators call can be found after this comment on the code // Monthly events Indicator Trigger value consumption-variation-monthly Tous les mois si l'utilisateur a \u00e9t\u00e9 connect\u00e9 au moins une fois dans le mois La variation de consomation par type de fluide. Les param\u00e8tres diff\u00e9rents sont le type de profil ainsi que le nombre de mois entre la premi\u00e8re connexion de l'utilisateur et le moment o\u00f9 est remont\u00e9 l'indicateur (seniority) summary-subscription-monthly Tous les mois si un utilisateur a souscrit a la newsletter ou c'est d\u00e9sabonn\u00e9 1 si l'utilsteur est inscrit sinon 0 fluid-data-granularity-monthly Tous les mois sans condition 1 si l'utilisateur poss\u00e8de de la donn\u00e9e a la demi heure sur le mois. Sinon 0 connection-count-monthly Tous les mois si il y a eu au moins une connexion Le nombre de jour unique de connexion profile-count-monthly Tous les mois si le profil a \u00e9t\u00e9 compl\u00e9t\u00e9 au moins une fois Le nombre de fois ou le profile a \u00e9t\u00e9 compl\u00e9t\u00e9 konnector-attempts-monthly Tous les mois, le nombre de tentative de connexion pour connecter un connecteur la premi\u00e8re fois. Une fois la connexion r\u00e9ussie, l'indicateur remonte 1 dans le groupe \"success\". L'indicateur ne remonte ensuite plus pour cet utilisateur car il aura d\u00e9j\u00e0 r\u00e9ussi \u00e0 se connecter une premi\u00e8re fois. Le nombre total de tentatives","title":"Monthly Indicators"},{"location":"ecolyo/functionalities/dacc/#daily-indicators","text":"The daily process get all events of previous day and process them in the following indicators Indicator Trigger value connection-count-daily Tous les jours Nombre de connexion. Celle-ci sont cat\u00e9goris\u00e9 par type (mobile ou desktop), bas\u00e9 sur le navigateur de l'utilisateur. (les tablettes sont compt\u00e9es comme des mobiles) konnector-event-daily Tous les jours Nombre d'essai. Ils sont cat\u00e9goris\u00e9 par type de connecteur, refresh/success et le status (error ou success) konnector-connected-daily Tous les jours La valeur est 1. Les valeurs sont cat\u00e9goris\u00e9es par type de fluide (electricity / electricity:water ...) navigation-count-daily Tous les jours nombre de page visualis\u00e9 par type de page challenge-launch-daily Tous les jours Nombre de d\u00e9fis lanc\u00e9s lors d'un challenge session-duration Tous les jours Dur\u00e9e de la session en secondes navigation-action-daily Tous les jours Nombre d'action sur une page donn\u00e9e. Exemple sur la consomation on trace les changements de pas de temps sur chaque graph. event-duration Tous les jours Dur\u00e9e entre deux \u00e9v\u00e9nements: 1ere session et premier challenge / d\u00e9but de challenge et fin de challenge / d\u00e9but d'exploration et fin d'exploration / d\u00e9but d'action et fin d'action / d\u00e9but de duel et fin de duel quiz-stars Tous les jours Nombre d'\u00e9toiles obtenu a la fin d'un quiz","title":"Daily Indicators"},{"location":"ecolyo/functionalities/dacc/#information-sending","text":"","title":"Information sending"},{"location":"ecolyo/functionalities/dacc/#format","text":"All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. The structure to send is the following : { createdBy: string measureName: string startDate: string value: number | null group1?: object group2?: object group3?: object } with: createdBy : contains \"ecolyo\" value. startDate : used to defined the start date of the indicator value : contains a value relevant to the defined indicator (example: number of page viewed on a day). groups : contains all attributes defining a indicator. Please refer to indicators definition (https://stats.cozycloud.cc/question#eyJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjo0LCJxdWVyeSI6eyJzb3VyY2UtdGFibGUiOjh9LCJ0eXBlIjoicXVlcnkifSwiZGlzcGxheSI6InRhYmxlIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319) mesureName : contains one of the following value ENUM value CONNECTION_COUNT_DAILY connection-count-daily KONNECTOR_EVENT_DAILY konnector-event-daily KONNECTOR_CONNECTED_PER_DAY konnector-connected-daily NAVIGATION_COUNT_DAILY navigation-count-daily CHALLENGE_LAUNCH_EVENT_DAILY challenge-launch-daily CONSUMPTION_VARIATION_MONTHLY consumption-variation-monthly SESSION_DURATION session-duration NAVIGATION_ACTION_DAILY navigation-action-daily EVENT_DURATION event-duration QUIZ_STARS quiz-stars SUMMARY_SUBSCRIPTION_MONTHLY summary-subscription-monthly FLUID_DATA_GRANULARITY fluid-data-granularity-monthly CONNECTION_COUNT_MONTHLY connection-count-monthly PROFILE_COUNT_MONTHLY profile-count-monthly KONNECTOR_ATTEMPTS_MONTHLY konnector-attempts-monthly","title":"Format"},{"location":"ecolyo/functionalities/dacc/#environnements","text":"There is two remote doctypes pointing to two differents mode. dacc-dev is used on alpha. \"dacc\" : { \"type\" : \"cc.cozycloud.dacc\" , \"verbs\" : [ \"ALL\" ] }, \"dacc-dev\" : { \"type\" : \"cc.cozycloud.dacc.dev\" , \"verbs\" : [ \"ALL\" ] },","title":"Environnements"},{"location":"ecolyo/functionalities/dacc/#how-to-local-test","text":"First you need to modify the service in order to be able to see data in local : Modify dacc URL in order to see data (ligne 67) await client . getStackClient () . fetchJSON ( 'POST' , environementService . isProduction () ? 'http://localhost:8081' : '/remote/cc.cozycloud.dacc.dev' , { data : JSON . stringify ( indicator ), } ) Remove date protection if you want to test monthly indicators (ligne 1100) if ( profile // && // DateTime.local() // .setZone('utc', { // keepLocalTime: true, // }) // .startOf('day').day === profile.monthlyAnalysisDate.day ) { Then you need to launch a script that will simulate dacc api's. This terminal will listen to incoming request cd ./scripts node server.js Then you are finaly ready to test ! Just run the following : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\a ggregatorUsageEvents \\e colyo.js You must see sent indicators in the previously open terminal { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' }","title":"How to local test ?"},{"location":"ecolyo/functionalities/dacc/#how-to-add-new-indicator","text":"You have to reach cozy and discuss with them about new indicators. They will implement it for dacc-dev and dacc and you will be able to test it on alpha env. Remember you will need at least 5 data of each type to see it in metabase.","title":"How to add new indicator ?"},{"location":"ecolyo/functionalities/dacc/#visualisation","text":"All the data aggregated in the dacc can be visualized with a Metabase website hosted by cozy (https://stats.cozycloud.cc/).","title":"Visualisation"},{"location":"ecolyo/functionalities/ecogesture/","text":"Ecogesture Description An ecogesture is a gesture that encourages user to take action for reduce their own consumption. It includes different information such as icon, name, long and short description, its efficiency on the consumption and which fluid is affected. Also, an ecogesture can be used for an action challenge. Model Ecogesture { id: string shortName: string longName: string longDescription: string usage: Usage fluidTypes: FluidType[] impactLevel: number efficiency: number difficulty: number room: Room[] season: Season equipment: boolean equipmentType: EquipmentType[] equipmentInstallation: boolean investment: string | null action: boolean actionName: string | null actionDuration: number objective: boolean doing: boolean viewedInSelection: boolean } Ecogestures screen This screen is divided in 3 tabs : - ALL : display the full list of ecogestures. User can filter ecogesture by usage. - DOING : display the list of doing ecogestures. User can filter ecogesture by usage. - OBJECTIVES : display the list of objectives ecogestures. User can filter ecogesture by usage. RULES By default the ALL tab is selected. If user click on an ecogesture, he will see more information about it and will be able to choose manually if it is doing AND/OR objective The back arrow button on a single ecogesture returns to the tab he came through. Ecogesture Status An ecogesture can have a status according the user's choice, it can be doing and/or objective which allows the user to consult them in the related tabs in the ecogesture page. On it is selected by the user in the tinder-like tunnel, the viewedInSelection key is set to true, so the user won't see it again in its selection. Profile Ecogesture The first time the user consults the ecogesture page, he will be prompted to start selecting his custom ecogestures. - If he refuses, I will still be able to access this functionnality by clicking on the \"Select\" button on the tabs 'Doing' and 'Objectives' while they are still empty. - If he starts select ecogestures on his own by the tab 'All' and fill both 'objective' and 'doing' sections, he won't be able to access the form and selection as described in the next parts. Model ProfileEcogesture { heating: IndividualOrCollective warmingFluid: WarmingType | null hotWater: IndividualOrCollective equipments: EquipmentType[] } Ecogesture Form The form is compose in 2 parts : - The first is made of question concerning his heating fluid and type (individual or collective), and his hotWater type. - The second part asks the user to pick the equipment he has. If the user has completed his profileType, he won't see the first part as it is automatically completed with the information he filled in his profileType The first part filters his custom list by Usages ECS and HEATING The second part filters his custom list by Equipments Ecogesture Selection Once user has completed his profile ecogesture through the form, he has the possibility to enter the ecogesture selection (tinder-like) - A list of custom ecogesture is made according to his profile - User will cross this list 10 by 10, and has to choose if it is 'doing' 'objective' or 'not interested Important Rules If uses refuses to do the selection for now, he will be reminded to do it in the 'doing' and 'objective' tabs, and a continue button will show User can go back and correct his answer at any time User can stop the process at any time, hist answer will be saved ad the next time he will open the selection, a new stack of 10 ecogesture is made (for example, user stops at 4/10, the next time he opens the selection it will be 4/14) If user chooses to select manually an ecogesture outside of the selection tunnel (through the 'all' tab), this ecogesture will be removed from the list it was existing in it. If user chosses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), thoose ecogestures won't be purposes again in the selection tunnel. User can't use the back arrow on the first ecogesture of selection list Once the whole process is done, the user has no possibility to do it again through the tinder-like selection, but he can still edit his ecogestures manually from the various tabs. Case ecogesture usage is heating We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual heating which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual heating which use gas fluid. Case ecogesture usage is ECS ECS = Eau chaude sanitaire We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual hot water which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual hot water which use gas fluid. Case ecogesture usage is Cooking We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an electricity fluid for cooking. OR the ecogesture has gas fluid and profile type has an gas fluid for cooking. Case ecogesture usage is cold water We will display the ecogesture if the profile type has individual cold water. Case ecogesture usage is specific electricity We will display the ecogesture. Case ecogesture usage is air conditioning We will NOT display the ecogesture.","title":"Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture","text":"","title":"Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#description","text":"An ecogesture is a gesture that encourages user to take action for reduce their own consumption. It includes different information such as icon, name, long and short description, its efficiency on the consumption and which fluid is affected. Also, an ecogesture can be used for an action challenge.","title":"Description"},{"location":"ecolyo/functionalities/ecogesture/#model","text":"Ecogesture { id: string shortName: string longName: string longDescription: string usage: Usage fluidTypes: FluidType[] impactLevel: number efficiency: number difficulty: number room: Room[] season: Season equipment: boolean equipmentType: EquipmentType[] equipmentInstallation: boolean investment: string | null action: boolean actionName: string | null actionDuration: number objective: boolean doing: boolean viewedInSelection: boolean }","title":"Model"},{"location":"ecolyo/functionalities/ecogesture/#ecogestures-screen","text":"This screen is divided in 3 tabs : - ALL : display the full list of ecogestures. User can filter ecogesture by usage. - DOING : display the list of doing ecogestures. User can filter ecogesture by usage. - OBJECTIVES : display the list of objectives ecogestures. User can filter ecogesture by usage.","title":"Ecogestures screen"},{"location":"ecolyo/functionalities/ecogesture/#rules","text":"By default the ALL tab is selected. If user click on an ecogesture, he will see more information about it and will be able to choose manually if it is doing AND/OR objective The back arrow button on a single ecogesture returns to the tab he came through.","title":"RULES"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-status","text":"An ecogesture can have a status according the user's choice, it can be doing and/or objective which allows the user to consult them in the related tabs in the ecogesture page. On it is selected by the user in the tinder-like tunnel, the viewedInSelection key is set to true, so the user won't see it again in its selection.","title":"Ecogesture Status"},{"location":"ecolyo/functionalities/ecogesture/#profile-ecogesture","text":"The first time the user consults the ecogesture page, he will be prompted to start selecting his custom ecogestures. - If he refuses, I will still be able to access this functionnality by clicking on the \"Select\" button on the tabs 'Doing' and 'Objectives' while they are still empty. - If he starts select ecogestures on his own by the tab 'All' and fill both 'objective' and 'doing' sections, he won't be able to access the form and selection as described in the next parts.","title":"Profile Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#model_1","text":"ProfileEcogesture { heating: IndividualOrCollective warmingFluid: WarmingType | null hotWater: IndividualOrCollective equipments: EquipmentType[] }","title":"Model"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-form","text":"The form is compose in 2 parts : - The first is made of question concerning his heating fluid and type (individual or collective), and his hotWater type. - The second part asks the user to pick the equipment he has. If the user has completed his profileType, he won't see the first part as it is automatically completed with the information he filled in his profileType The first part filters his custom list by Usages ECS and HEATING The second part filters his custom list by Equipments","title":"Ecogesture Form"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-selection","text":"Once user has completed his profile ecogesture through the form, he has the possibility to enter the ecogesture selection (tinder-like) - A list of custom ecogesture is made according to his profile - User will cross this list 10 by 10, and has to choose if it is 'doing' 'objective' or 'not interested","title":"Ecogesture Selection"},{"location":"ecolyo/functionalities/ecogesture/#important-rules","text":"If uses refuses to do the selection for now, he will be reminded to do it in the 'doing' and 'objective' tabs, and a continue button will show User can go back and correct his answer at any time User can stop the process at any time, hist answer will be saved ad the next time he will open the selection, a new stack of 10 ecogesture is made (for example, user stops at 4/10, the next time he opens the selection it will be 4/14) If user chooses to select manually an ecogesture outside of the selection tunnel (through the 'all' tab), this ecogesture will be removed from the list it was existing in it. If user chosses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), thoose ecogestures won't be purposes again in the selection tunnel. User can't use the back arrow on the first ecogesture of selection list Once the whole process is done, the user has no possibility to do it again through the tinder-like selection, but he can still edit his ecogestures manually from the various tabs.","title":"Important Rules"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-heating","text":"We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual heating which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual heating which use gas fluid.","title":"Case ecogesture usage is heating"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-ecs","text":"ECS = Eau chaude sanitaire We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual hot water which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual hot water which use gas fluid.","title":"Case ecogesture usage is ECS"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-cooking","text":"We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an electricity fluid for cooking. OR the ecogesture has gas fluid and profile type has an gas fluid for cooking.","title":"Case ecogesture usage is Cooking"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-cold-water","text":"We will display the ecogesture if the profile type has individual cold water.","title":"Case ecogesture usage is cold water"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-specific-electricity","text":"We will display the ecogesture.","title":"Case ecogesture usage is specific electricity"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-air-conditioning","text":"We will NOT display the ecogesture.","title":"Case ecogesture usage is air conditioning"},{"location":"ecolyo/functionalities/feedback/","text":"Feedback Users can send a feedback in the application, the feedback's receiver is defined in the FeedbackModal component Add mail attachments The user has the possibility to add an image to a feedback. The email informations are created in the sendEmail function and the mailData respects this scheme : const mailData = { mode : \"from\" , to : [{ name : \"Support\" , email : \"receiver-email\" }], subject : \"Your subject\" , parts : [{ type : \"text/plain\" , body : mailContent }], attachments : [{ filename : \"test.png\" , content : \"base64file\" }], }; It is important that your file is sent base64 encoded to the sendmail job and with the data...base64 headers removed, otherwise it will be unreadable. In order to do this, we use a reader to read the file as Data URL reader . readAsDataURL ( file ); and then apply to the result so we send only the encoded part without its headers. split ( \",\" )[ 1 ];","title":"Feedback"},{"location":"ecolyo/functionalities/feedback/#feedback","text":"Users can send a feedback in the application, the feedback's receiver is defined in the FeedbackModal component","title":"Feedback"},{"location":"ecolyo/functionalities/feedback/#add-mail-attachments","text":"The user has the possibility to add an image to a feedback. The email informations are created in the sendEmail function and the mailData respects this scheme : const mailData = { mode : \"from\" , to : [{ name : \"Support\" , email : \"receiver-email\" }], subject : \"Your subject\" , parts : [{ type : \"text/plain\" , body : mailContent }], attachments : [{ filename : \"test.png\" , content : \"base64file\" }], }; It is important that your file is sent base64 encoded to the sendmail job and with the data...base64 headers removed, otherwise it will be unreadable. In order to do this, we use a reader to read the file as Data URL reader . readAsDataURL ( file ); and then apply to the result so we send only the encoded part without its headers. split ( \",\" )[ 1 ];","title":"Add mail attachments"},{"location":"ecolyo/functionalities/initialization/","text":"This section explains how to handle data storage. We handle data storage according to the following process : The folder /src/db contains all the JSON entities that are directly stored in the couchDB during the initialization process that is executed in the splash screen. They are stored under their related doctype. Initialization and Updating During the initialization process, we store a hash for each dataEntity that is likely to be changed or updated. The hash is stored in the userProfile. [ { \"ecogestureHash\" : \"\" , \"challengeHash\" : \"\" , \"quizHash\" : \"\" , \"explorationHash\" : \"\" , \"duelHash\" : \"\" , \"isFirstConnection\" : true , \"haveSeenFavoriteModal\" : false , \"haveSeenOldFluidModal\" : false , \"haveSeenLastReport\" : true , \"sendReportNotification\" : false , \"monthlyReportDate\" : \"0000-01-01T00:00:00.000Z\" } ] This way, once the initialization is launched, we compare the hash we have in the current userProfile with the one generated from the entity located in /db folder, and if they are different we update the couchDB with the new data. In order to handle this process, each entity that is likely to change has a function that takes the current hash in entry, and execute the following process : creates a hash from the related entity file (for example EcogestureData.json ) get the entities from the database if there is no entity stored, populates the related doctype (for this example ECOGESTURE_DOCTYPE ) for each item stored in the entity file compare the number of entries created in the doctype with the number of item in the entity file if the previous hash and the new hash are different, delete all entries in the doctype and populates with the items stored in the entity file Functions used to init or update the hash : Function initEcogesture(hash: string) initChallengeEntity(hash: string) initDuelEntity(hash: string) initQuizEntity(hash: string) initExplorationEntity(hash: string) Exception for ecogestures When we update the ecogesture list in ecogestureData.json , we also get the previous existing list to transfer the ecogesture status (doing and/or objective) to the updated list. dataEntity vs userData In the project, you'll see two versions for the same data. The dataEntity (quizEntity, challengeEntity, ...) is the data stored in the db folder and in the couchDB. These data are only edited in the couchDB when we update a challenge/quiz/duel or add a new one. The userData (userChallenge, userQuiz...) is created from the entity and extended with user's data, such as his progress, his consumption data, goals, fails etc. Using this 2 structures allows us to keep user's datas when we'll update the application, by editing just the entities. Relationships Relationships is a functionality made by cozy, they are built with the name of the relation, containing a \"data\" object, itself containing the id of the related item and its doctype \"_type\". Using this allows us to reduce the size of the stored items and increase readability. Relations are set as HasOne relationships for Quiz and Duel because there is only one quiz and one duel for Challenge. Thus, we use a HasMany relation for the Exploration , because one challenge can have several exploration in order the handle the specific cases of fluid-based explorations. You can see more about relationships on cozy documentation . \"relationships\" : { \"quiz\" : { \"data\" : { \"_id\" : \"QUIZ001\" , \"_type\" : \"com.grandlyon.ecolyo.quiz\" } }, \"duel\" : { \"data\" : { \"_id\" : \"DUEL001\" , \"_type\" : \"com.grandlyon.ecolyo.duel\" } }, \"exploration\" : { \"data\" : [ { \"_id\" : \"EXPLORATION001\" , \"_type\" : \"com.grandlyon.ecolyo.exploration\" } ] } } UserData creation We create a userData and store it in the couchDB under the doctype userData name ' com.grandlyon.ecolyo.userDataName'. During this process, the objects related to the dataEntity will be be converted to an user version which contains informations about the user(example: user progress, the fluids connected and so on). To illustrate this, let's show an example of the conversion of duelEntity to UserDuel : DuelEntity { id: string title: string description: string duration: Duration } Becomes : UserDuel { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: DateTime | null fluidTypes: FluidType[] userConsumption: number } Since we use the Luxon library for DateTimes, we need to have an intermediate interface for the UserDuel. Indeed, the database doesn't know the DateTime type, so when we query a UserDuel, its startDate property is a string and not a DateTime . The solve this and avoid Typescript errors, we created the following interface : UserDuelEntity { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: string | null fluidTypes: FluidType[] userConsumption: number } Data managment schema Loader The initialization process displays progression steps in the splash screen so the user can see what is happening while it is loading. Each initialization function set an error if it fails, which is shown on the Slpash error screnn. Available loading steps are the followings : ```` MIGRATION = 0, CONSENT = 1, PROFILE = 2, ECOGESTURE = 3, CHALLENGES = 4, PRICES = 5, CONSOS = 6, ``` Possible errors are the followings : MIGRATION_ERROR = 'migration_error', CONSENT_ERROR = 'consent_error', PROFILE_ERROR = 'profile_error', PROFILETYPE_ERROR = 'profileType_error', ECOGESTURE_ERROR = 'ecogesture_error', CHALLENGES_ERROR = 'challenges_error', ANALYSIS_ERROR = 'analysis_error', INDEX_ERROR = 'index_error', PRICES_ERROR = 'prices_error', CONSOS_ERROR = 'consos_error', PARTNERS_ERROR = 'partners_error', UNKNOWN_ERROR = 'unknown_error',","title":"Initialization"},{"location":"ecolyo/functionalities/initialization/#initialization-and-updating","text":"During the initialization process, we store a hash for each dataEntity that is likely to be changed or updated. The hash is stored in the userProfile. [ { \"ecogestureHash\" : \"\" , \"challengeHash\" : \"\" , \"quizHash\" : \"\" , \"explorationHash\" : \"\" , \"duelHash\" : \"\" , \"isFirstConnection\" : true , \"haveSeenFavoriteModal\" : false , \"haveSeenOldFluidModal\" : false , \"haveSeenLastReport\" : true , \"sendReportNotification\" : false , \"monthlyReportDate\" : \"0000-01-01T00:00:00.000Z\" } ] This way, once the initialization is launched, we compare the hash we have in the current userProfile with the one generated from the entity located in /db folder, and if they are different we update the couchDB with the new data. In order to handle this process, each entity that is likely to change has a function that takes the current hash in entry, and execute the following process : creates a hash from the related entity file (for example EcogestureData.json ) get the entities from the database if there is no entity stored, populates the related doctype (for this example ECOGESTURE_DOCTYPE ) for each item stored in the entity file compare the number of entries created in the doctype with the number of item in the entity file if the previous hash and the new hash are different, delete all entries in the doctype and populates with the items stored in the entity file Functions used to init or update the hash : Function initEcogesture(hash: string) initChallengeEntity(hash: string) initDuelEntity(hash: string) initQuizEntity(hash: string) initExplorationEntity(hash: string) Exception for ecogestures When we update the ecogesture list in ecogestureData.json , we also get the previous existing list to transfer the ecogesture status (doing and/or objective) to the updated list.","title":"Initialization and Updating"},{"location":"ecolyo/functionalities/initialization/#dataentity-vs-userdata","text":"In the project, you'll see two versions for the same data. The dataEntity (quizEntity, challengeEntity, ...) is the data stored in the db folder and in the couchDB. These data are only edited in the couchDB when we update a challenge/quiz/duel or add a new one. The userData (userChallenge, userQuiz...) is created from the entity and extended with user's data, such as his progress, his consumption data, goals, fails etc. Using this 2 structures allows us to keep user's datas when we'll update the application, by editing just the entities.","title":"dataEntity vs userData"},{"location":"ecolyo/functionalities/initialization/#relationships","text":"Relationships is a functionality made by cozy, they are built with the name of the relation, containing a \"data\" object, itself containing the id of the related item and its doctype \"_type\". Using this allows us to reduce the size of the stored items and increase readability. Relations are set as HasOne relationships for Quiz and Duel because there is only one quiz and one duel for Challenge. Thus, we use a HasMany relation for the Exploration , because one challenge can have several exploration in order the handle the specific cases of fluid-based explorations. You can see more about relationships on cozy documentation . \"relationships\" : { \"quiz\" : { \"data\" : { \"_id\" : \"QUIZ001\" , \"_type\" : \"com.grandlyon.ecolyo.quiz\" } }, \"duel\" : { \"data\" : { \"_id\" : \"DUEL001\" , \"_type\" : \"com.grandlyon.ecolyo.duel\" } }, \"exploration\" : { \"data\" : [ { \"_id\" : \"EXPLORATION001\" , \"_type\" : \"com.grandlyon.ecolyo.exploration\" } ] } }","title":"Relationships"},{"location":"ecolyo/functionalities/initialization/#userdata-creation","text":"We create a userData and store it in the couchDB under the doctype userData name ' com.grandlyon.ecolyo.userDataName'. During this process, the objects related to the dataEntity will be be converted to an user version which contains informations about the user(example: user progress, the fluids connected and so on). To illustrate this, let's show an example of the conversion of duelEntity to UserDuel : DuelEntity { id: string title: string description: string duration: Duration } Becomes : UserDuel { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: DateTime | null fluidTypes: FluidType[] userConsumption: number } Since we use the Luxon library for DateTimes, we need to have an intermediate interface for the UserDuel. Indeed, the database doesn't know the DateTime type, so when we query a UserDuel, its startDate property is a string and not a DateTime . The solve this and avoid Typescript errors, we created the following interface : UserDuelEntity { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: string | null fluidTypes: FluidType[] userConsumption: number }","title":"UserData creation"},{"location":"ecolyo/functionalities/initialization/#data-managment-schema","text":"","title":"Data managment schema"},{"location":"ecolyo/functionalities/initialization/#loader","text":"The initialization process displays progression steps in the splash screen so the user can see what is happening while it is loading. Each initialization function set an error if it fails, which is shown on the Slpash error screnn. Available loading steps are the followings : ```` MIGRATION = 0, CONSENT = 1, PROFILE = 2, ECOGESTURE = 3, CHALLENGES = 4, PRICES = 5, CONSOS = 6, ``` Possible errors are the followings : MIGRATION_ERROR = 'migration_error', CONSENT_ERROR = 'consent_error', PROFILE_ERROR = 'profile_error', PROFILETYPE_ERROR = 'profileType_error', ECOGESTURE_ERROR = 'ecogesture_error', CHALLENGES_ERROR = 'challenges_error', ANALYSIS_ERROR = 'analysis_error', INDEX_ERROR = 'index_error', PRICES_ERROR = 'prices_error', CONSOS_ERROR = 'consos_error', PARTNERS_ERROR = 'partners_error', UNKNOWN_ERROR = 'unknown_error',","title":"Loader"},{"location":"ecolyo/functionalities/onboarding/","text":"This section explains the way we handle onboarding the application. Description When the user connects for the first time to Ecolyo, onboarding screens will be displayed. First connection The first connection is define by the isFirstConnection boolean contains in the profile doctype. GCU screen First of all, we display the GCU screen, which allows user to read the General Condition of Use and the Legal Notive. The user should consent to all the terms to go further in the application. About terms More details are available on the (term section)[/ecolyo/functionalities/terms.md]. Welcome modal After GCU screen we display a welcome modal to inform user about further steps needed to use Ecolyo (connection to partners to retrieve the data, ...). We store in user's profile a boolean onboarding.isWelcomeSeen that allows the app to know is the modal has already be seen. If the modal has been seen we will never display it again. When user close this modal, the welcome mail is sent to the user.","title":"Onboarding"},{"location":"ecolyo/functionalities/onboarding/#description","text":"When the user connects for the first time to Ecolyo, onboarding screens will be displayed. First connection The first connection is define by the isFirstConnection boolean contains in the profile doctype.","title":"Description"},{"location":"ecolyo/functionalities/onboarding/#gcu-screen","text":"First of all, we display the GCU screen, which allows user to read the General Condition of Use and the Legal Notive. The user should consent to all the terms to go further in the application. About terms More details are available on the (term section)[/ecolyo/functionalities/terms.md].","title":"GCU screen"},{"location":"ecolyo/functionalities/onboarding/#welcome-modal","text":"After GCU screen we display a welcome modal to inform user about further steps needed to use Ecolyo (connection to partners to retrieve the data, ...). We store in user's profile a boolean onboarding.isWelcomeSeen that allows the app to know is the modal has already be seen. If the modal has been seen we will never display it again. When user close this modal, the welcome mail is sent to the user.","title":"Welcome modal"},{"location":"ecolyo/functionalities/prices_calculation/","text":"Price Calculation This section explains the price calculation process. Description Since version 1.6.0 of the app, we have a database storing fluid prices evolution sincre 2012 for the following fluids : * Elecricity * Gas Before this version, the app was applying a hard coded price for each fluid without taking care of the time period. Now, there is a service running every night that process fresh data in order to apply the current price to this data, but also apply the most relevant price for a fluid doctype. Service Process The Cozy service responsible for price calculation is fluidsPrices . You can find the full logic in the following diagram : This service is running every night at 02:00 AM. note You might observe some price miscalculation if data from konnector is collect after the service runtime. Because of the hard code price, which is the current price, the user should not see any difference. Init A migration job has been setup to init the database with json data store inside the app. This job should be run once and will init electricy and gas prices. New price In case of price update the following procedure must be done : * Create a migration for adding new prices * Update hard coded price inside app in order to maintain fallback calculation * Verify full service calculation with new data * Verify calculation with existing data note The service does not handle change during a month because the case does not exist anymore for Enedis and Grdf. Prices Data We store in databse a collection of prices with the following info : * StartDate * EndDate * fluidType * Price The EndDate is set to null if it's the current fluid price. App Price display The app can handle the new price calculation and also keep the old calculation system. Regular display If there is a price on the doctype we want to process, it will be use for display and calculation ( see analysis functionality). Fallback The app take the hard code price for a given fluid and apply it to a load. This allow the app to handle prices in any case. How to test service ? In a shell run a build and test service with le following command line : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\m onthlyReport \\e colyo.js Evolutions We might consider a more dynamic process for fallback price calculation in the future: * Get last price for a given price in database * Use it to calculate value instead of the hard coded one * Use it in all info pop-in for user information","title":"Price Calculation"},{"location":"ecolyo/functionalities/prices_calculation/#price-calculation","text":"This section explains the price calculation process.","title":"Price Calculation"},{"location":"ecolyo/functionalities/prices_calculation/#description","text":"Since version 1.6.0 of the app, we have a database storing fluid prices evolution sincre 2012 for the following fluids : * Elecricity * Gas Before this version, the app was applying a hard coded price for each fluid without taking care of the time period. Now, there is a service running every night that process fresh data in order to apply the current price to this data, but also apply the most relevant price for a fluid doctype.","title":"Description"},{"location":"ecolyo/functionalities/prices_calculation/#service","text":"","title":"Service"},{"location":"ecolyo/functionalities/prices_calculation/#process","text":"The Cozy service responsible for price calculation is fluidsPrices . You can find the full logic in the following diagram : This service is running every night at 02:00 AM. note You might observe some price miscalculation if data from konnector is collect after the service runtime. Because of the hard code price, which is the current price, the user should not see any difference.","title":"Process"},{"location":"ecolyo/functionalities/prices_calculation/#init","text":"A migration job has been setup to init the database with json data store inside the app. This job should be run once and will init electricy and gas prices.","title":"Init"},{"location":"ecolyo/functionalities/prices_calculation/#new-price","text":"In case of price update the following procedure must be done : * Create a migration for adding new prices * Update hard coded price inside app in order to maintain fallback calculation * Verify full service calculation with new data * Verify calculation with existing data note The service does not handle change during a month because the case does not exist anymore for Enedis and Grdf.","title":"New price"},{"location":"ecolyo/functionalities/prices_calculation/#prices-data","text":"We store in databse a collection of prices with the following info : * StartDate * EndDate * fluidType * Price The EndDate is set to null if it's the current fluid price.","title":"Prices Data"},{"location":"ecolyo/functionalities/prices_calculation/#app-price-display","text":"The app can handle the new price calculation and also keep the old calculation system.","title":"App Price display"},{"location":"ecolyo/functionalities/prices_calculation/#regular-display","text":"If there is a price on the doctype we want to process, it will be use for display and calculation ( see analysis functionality).","title":"Regular display"},{"location":"ecolyo/functionalities/prices_calculation/#fallback","text":"The app take the hard code price for a given fluid and apply it to a load. This allow the app to handle prices in any case.","title":"Fallback"},{"location":"ecolyo/functionalities/prices_calculation/#how-to-test-service","text":"In a shell run a build and test service with le following command line : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\m onthlyReport \\e colyo.js","title":"How to test service ?"},{"location":"ecolyo/functionalities/prices_calculation/#evolutions","text":"We might consider a more dynamic process for fallback price calculation in the future: * Get last price for a given price in database * Use it to calculate value instead of the hard coded one * Use it in all info pop-in for user information","title":"Evolutions"},{"location":"ecolyo/functionalities/profile_type/","text":"This section explains the profileType creation process in order to make different comparisons between the actual user's consumption and its profile type. Profile type data The profileType data are stored in the profile doctype and includes the following informations : { housingType: HousingType constructionYear: ConstructionYear area: string occupantsNumber: number outsideFacingWalls: OutsideFacingWalls floor: Floor heating: IndividualOrCollective coldWater: IndividualOrCollective hotWater: IndividualOrCollective individualInsulationWork: IndividualInsulationWork[] hasInstalledVentilation: ThreeChoicesAnswer hasReplacedHeater: ThreeChoicesAnswer hotWaterEquipment: HotWaterEquipment warmingFluid: WarmingType | null hotWaterFluid: FluidType | null cookingFluid: FluidType updateDate: DateTime } Each profileType value is an enum that you can find in the application. The values are set by default to a default profileType and needs to be completed by the user in order to become accurate. Profile type form User should answer a form to be able to set its profile type. Here is the flow of questions: Profile types handling over time A user can have many profileTypes, Ecolyo takes into account that one can move from his home, have more occupants, start renovating works and so on. That's why a profileType is only active for a given time period, this is how its time logic works. No filled profileType A default profileType is loaded in redux to operate basic operations. When the user looks at its analysis or options, ecolyo suggest user to fill a more accurate profileType. First profileType The profileType will follow the form logic above (see ProfileType form section). updateDate field will be the current month and year. Since this profileType will be the only one in database, getProfileType() method will always return it, therefore it will be used for all past time period on analysis. Following profileTypes Each new profileType form will show a calendar picking section at the end of the form. By default, current month and year will be selected. If current year is not yet completed (december not reached), month dropdown menu will only propose past and present months for this year. When finishing, before the new profileType is saved. Checks if other profileTypes exist on the period between selected month/year and present day. - If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some informations before, this new profiletype will be more accurate). Then save profileType on given month/year. - If no other profileTypes are found, save profileType on given month/year. Profile type entity service Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getProfileType(date?: DateTime) : Promise-ProfileType, null Returns a profiletype closest to the given param date. When no param date, returns most recent profiletype getAllProfileTypes(timePeriod?: TimePeriod) : Promise-ProfileType[], null Returns all profiletypes for given time period, if no param returns all profiletypes updateProfileType(attributes: Partial-ProfileType): Promise-ProfileType, null Saves profiletype in couchdb deleteProfileTypes(profileTypes: ProfileType[]): Promise-boolean Delete array of profileTypes parseProfileTypeEntityToProfileType(profileTypeEntity: ProfileType): ProfileType Retrieves ProfileType from the ProfileTypeEntity Profile type service Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getMonthlyForecast(month: number) : Promise-MonthlyForecast Used to get the monthly forecast for a given month getFluidForecast(fluidType: FluidType, month: number) : Promise-FluidForecast Used to get the monthly forecast for a given FluidType getDetailsMonthlyForecast(fluidType: FluidType, month: number): Promise-DetailsMonthlyForecast Used to get the details of a fluidForecast. For each fluid return the related consumptions getMonthColdWaterConsumption(month: number): number Returns the cold water consumption in L for a given month getMonthElectricSpecificConsumption(month: number): number Returns the electric specific consumption in kWh for a given month getMonthCookingConsumption(month: number): number Returns the cooking consumption in kWh for a given month getMonthEcs(month: number) : number Returns the hot water consumption in kWh for a given month getMonthHeating(month: number): Promise-number Returns the heating consumption in kWh for a given month calculateTotalConsumption(spreadConsumption: number, profileType: ProfileType, month: number) : number Returns the total ECS consumption with applyied corrections to the spreadConsumption depending on users facilities. calculateSpreadNeeds(profileType: ProfileType, month: number): number Calculate the water spread consumption calculateMonthWaterRawNeeds(profileType: ProfileType, month: number) : number Returns the raw water needs of a home calculateWarmingEstimatedConsumption(): number Calculates the estimated consumption of a home calculateWarmingCorrectedConsumption(estimatedConsumption: number): number Apply the different corrections to the estimated heating consumption calculateWarmingMonthConsumption(correctedConsumption: number, month: number): Promise-number Apply dju ratio to the corrected heating consumption fetchDJU(month: number): Promise-number Returns a Promise with the dju for the given month Here is an example of a MonthlyForecast, which is the only function directly called by the analyzis component : { fluidForecast: [ { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: 266, heatingConsumption: 4074, }, fluidType: 0, load: 4340, value: 670.96, }, { detailsMonthlyForecast: { coldWaterConsumption: 14911, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 1, load: 14911, value: 46.224, }, { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: 85, ecsConsumption: 290, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 2, load: 375, value: 29.737, }, ], month: 1, totalValue: 746.921, } In these data, the load is in kWh for gaz and electricity (fluidtype 0 and 2) and in L for water. Value and totalValue are given in euros. The different consumption are distributed to their corresponding fluidType according to the variables warmingFluid, hotWaterFluid, cookingFluid . For example, if the cookingFluid is gaz, then its value will be stored in the fluidType 2 and nulled in the others. Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personnal consumption, so it doesn't takes place in the calculation. DJU The method fetchDJU(month:number) tries to fetch the daily dju from the datagrandlyon API trough a remote doctype named org.ecolyo.dju . The data returned by this API are gathered by the lyon-bron-sta The API returns dju by day for a given month, so we add them to return a monthly dju. If remote doctype fails or return a null value, we returns instead the default dju stored in heating.json Usefull tips while working with this API : Do not pass a Content-Type while requesting, it will returns error While requesting from a cozy instance, if you get errors, you will get errors from the cozy stack and not directly from the API, which leads to weird cases : If there is an authentication error, the api will returns an error in html format to cozy, so you'll get from cozy an error 502 as following, beacause cozy expects a json response : { \"status\" : \"502\" , \"title\" : \"Bad Gateway\" , \"detail\" : \"the content-type for the response is not authorized\" , \"source\" : {} } In case of bad request (wrong paramaters for example), the API will return an error in xml format so you'll get exaclty the same error as above in your cozy instance.","title":"Profile Type"},{"location":"ecolyo/functionalities/profile_type/#profile-type-data","text":"The profileType data are stored in the profile doctype and includes the following informations : { housingType: HousingType constructionYear: ConstructionYear area: string occupantsNumber: number outsideFacingWalls: OutsideFacingWalls floor: Floor heating: IndividualOrCollective coldWater: IndividualOrCollective hotWater: IndividualOrCollective individualInsulationWork: IndividualInsulationWork[] hasInstalledVentilation: ThreeChoicesAnswer hasReplacedHeater: ThreeChoicesAnswer hotWaterEquipment: HotWaterEquipment warmingFluid: WarmingType | null hotWaterFluid: FluidType | null cookingFluid: FluidType updateDate: DateTime } Each profileType value is an enum that you can find in the application. The values are set by default to a default profileType and needs to be completed by the user in order to become accurate.","title":"Profile type data"},{"location":"ecolyo/functionalities/profile_type/#profile-type-form","text":"User should answer a form to be able to set its profile type. Here is the flow of questions:","title":"Profile type form"},{"location":"ecolyo/functionalities/profile_type/#profile-types-handling-over-time","text":"A user can have many profileTypes, Ecolyo takes into account that one can move from his home, have more occupants, start renovating works and so on. That's why a profileType is only active for a given time period, this is how its time logic works.","title":"Profile types handling over time"},{"location":"ecolyo/functionalities/profile_type/#no-filled-profiletype","text":"A default profileType is loaded in redux to operate basic operations. When the user looks at its analysis or options, ecolyo suggest user to fill a more accurate profileType.","title":"No filled profileType"},{"location":"ecolyo/functionalities/profile_type/#first-profiletype","text":"The profileType will follow the form logic above (see ProfileType form section). updateDate field will be the current month and year. Since this profileType will be the only one in database, getProfileType() method will always return it, therefore it will be used for all past time period on analysis.","title":"First profileType"},{"location":"ecolyo/functionalities/profile_type/#following-profiletypes","text":"Each new profileType form will show a calendar picking section at the end of the form. By default, current month and year will be selected. If current year is not yet completed (december not reached), month dropdown menu will only propose past and present months for this year. When finishing, before the new profileType is saved. Checks if other profileTypes exist on the period between selected month/year and present day. - If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some informations before, this new profiletype will be more accurate). Then save profileType on given month/year. - If no other profileTypes are found, save profileType on given month/year.","title":"Following profileTypes"},{"location":"ecolyo/functionalities/profile_type/#profile-type-entity-service","text":"Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getProfileType(date?: DateTime) : Promise-ProfileType, null Returns a profiletype closest to the given param date. When no param date, returns most recent profiletype getAllProfileTypes(timePeriod?: TimePeriod) : Promise-ProfileType[], null Returns all profiletypes for given time period, if no param returns all profiletypes updateProfileType(attributes: Partial-ProfileType): Promise-ProfileType, null Saves profiletype in couchdb deleteProfileTypes(profileTypes: ProfileType[]): Promise-boolean Delete array of profileTypes parseProfileTypeEntityToProfileType(profileTypeEntity: ProfileType): ProfileType Retrieves ProfileType from the ProfileTypeEntity","title":"Profile type entity service"},{"location":"ecolyo/functionalities/profile_type/#profile-type-service","text":"Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getMonthlyForecast(month: number) : Promise-MonthlyForecast Used to get the monthly forecast for a given month getFluidForecast(fluidType: FluidType, month: number) : Promise-FluidForecast Used to get the monthly forecast for a given FluidType getDetailsMonthlyForecast(fluidType: FluidType, month: number): Promise-DetailsMonthlyForecast Used to get the details of a fluidForecast. For each fluid return the related consumptions getMonthColdWaterConsumption(month: number): number Returns the cold water consumption in L for a given month getMonthElectricSpecificConsumption(month: number): number Returns the electric specific consumption in kWh for a given month getMonthCookingConsumption(month: number): number Returns the cooking consumption in kWh for a given month getMonthEcs(month: number) : number Returns the hot water consumption in kWh for a given month getMonthHeating(month: number): Promise-number Returns the heating consumption in kWh for a given month calculateTotalConsumption(spreadConsumption: number, profileType: ProfileType, month: number) : number Returns the total ECS consumption with applyied corrections to the spreadConsumption depending on users facilities. calculateSpreadNeeds(profileType: ProfileType, month: number): number Calculate the water spread consumption calculateMonthWaterRawNeeds(profileType: ProfileType, month: number) : number Returns the raw water needs of a home calculateWarmingEstimatedConsumption(): number Calculates the estimated consumption of a home calculateWarmingCorrectedConsumption(estimatedConsumption: number): number Apply the different corrections to the estimated heating consumption calculateWarmingMonthConsumption(correctedConsumption: number, month: number): Promise-number Apply dju ratio to the corrected heating consumption fetchDJU(month: number): Promise-number Returns a Promise with the dju for the given month Here is an example of a MonthlyForecast, which is the only function directly called by the analyzis component : { fluidForecast: [ { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: 266, heatingConsumption: 4074, }, fluidType: 0, load: 4340, value: 670.96, }, { detailsMonthlyForecast: { coldWaterConsumption: 14911, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 1, load: 14911, value: 46.224, }, { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: 85, ecsConsumption: 290, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 2, load: 375, value: 29.737, }, ], month: 1, totalValue: 746.921, } In these data, the load is in kWh for gaz and electricity (fluidtype 0 and 2) and in L for water. Value and totalValue are given in euros. The different consumption are distributed to their corresponding fluidType according to the variables warmingFluid, hotWaterFluid, cookingFluid . For example, if the cookingFluid is gaz, then its value will be stored in the fluidType 2 and nulled in the others. Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personnal consumption, so it doesn't takes place in the calculation.","title":"Profile type service"},{"location":"ecolyo/functionalities/profile_type/#dju","text":"The method fetchDJU(month:number) tries to fetch the daily dju from the datagrandlyon API trough a remote doctype named org.ecolyo.dju . The data returned by this API are gathered by the lyon-bron-sta The API returns dju by day for a given month, so we add them to return a monthly dju. If remote doctype fails or return a null value, we returns instead the default dju stored in heating.json Usefull tips while working with this API : Do not pass a Content-Type while requesting, it will returns error While requesting from a cozy instance, if you get errors, you will get errors from the cozy stack and not directly from the API, which leads to weird cases : If there is an authentication error, the api will returns an error in html format to cozy, so you'll get from cozy an error 502 as following, beacause cozy expects a json response : { \"status\" : \"502\" , \"title\" : \"Bad Gateway\" , \"detail\" : \"the content-type for the response is not authorized\" , \"source\" : {} } In case of bad request (wrong paramaters for example), the API will return an error in xml format so you'll get exaclty the same error as above in your cozy instance.","title":"DJU"},{"location":"ecolyo/functionalities/terms/","text":"This section explains the way we handle terms in the application. Description The terms version is handled with the io.cozy.terms doctype. It is incremented each time we edit the CGU, the data consent validation or the legal notices. Once we increment the terms version, the user will be prompted to accept these terms, otherwise we won't be able to access the app. Private Routes All routes are private, and are accessible only if the user has accepted the last version of the terms. The only public routes are : /terms : shows the terms validation page, and is the main page the user is redirected to if his consent is outdated /cgu : shows the CGU public page, accessible by the terms page /legal : shows the Legal Notice public page, accessible by the terms page Terms managment We check the terms acceptation in the SplashScreen while the application is initializing, if there is no consent (first connexion), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page. For the full terms acceptation process, the user has to check the two checboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value accepted to true. So he can access now the entire application. We store in user's profile a boolean showConsentModal that allows the app to know about the consent status. If there is a consent update, two cases are possible : - It's a major update, ex: from 1.X.X to 2.X.X, the user has to go through the entire term validation process as explained above - It's a minor update, ex: from 1.1.X to 1.3.X or from 1.2.1 to 1.2.3, the user is just prompted with a modal with some text about the update, and a link to the legal notice, but there is no blocking acceptation input for the user. Version number The version number of the last terms is stored in the config.json file. If this version number doesn't correspond with the last term accepted, according the update version type (minor or major), the user won't be able to access the app and will be prompted to accept new terms or will simply be prompted. Global state Once the verification done in the SplashScreen , the last term state is stored in the redux store under the ecolyo.global state. The model is the following : termsStatus: { accepted: boolean, versionType: 'major' | 'minor' | 'init', }, Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connexion or to case the last accepted term version is uptodate.","title":"Terms"},{"location":"ecolyo/functionalities/terms/#description","text":"The terms version is handled with the io.cozy.terms doctype. It is incremented each time we edit the CGU, the data consent validation or the legal notices. Once we increment the terms version, the user will be prompted to accept these terms, otherwise we won't be able to access the app.","title":"Description"},{"location":"ecolyo/functionalities/terms/#private-routes","text":"All routes are private, and are accessible only if the user has accepted the last version of the terms. The only public routes are : /terms : shows the terms validation page, and is the main page the user is redirected to if his consent is outdated /cgu : shows the CGU public page, accessible by the terms page /legal : shows the Legal Notice public page, accessible by the terms page","title":"Private Routes"},{"location":"ecolyo/functionalities/terms/#terms-managment","text":"We check the terms acceptation in the SplashScreen while the application is initializing, if there is no consent (first connexion), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page. For the full terms acceptation process, the user has to check the two checboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value accepted to true. So he can access now the entire application. We store in user's profile a boolean showConsentModal that allows the app to know about the consent status. If there is a consent update, two cases are possible : - It's a major update, ex: from 1.X.X to 2.X.X, the user has to go through the entire term validation process as explained above - It's a minor update, ex: from 1.1.X to 1.3.X or from 1.2.1 to 1.2.3, the user is just prompted with a modal with some text about the update, and a link to the legal notice, but there is no blocking acceptation input for the user.","title":"Terms managment"},{"location":"ecolyo/functionalities/terms/#version-number","text":"The version number of the last terms is stored in the config.json file. If this version number doesn't correspond with the last term accepted, according the update version type (minor or major), the user won't be able to access the app and will be prompted to accept new terms or will simply be prompted.","title":"Version number"},{"location":"ecolyo/functionalities/terms/#global-state","text":"Once the verification done in the SplashScreen , the last term state is stored in the redux store under the ecolyo.global state. The model is the following : termsStatus: { accepted: boolean, versionType: 'major' | 'minor' | 'init', }, Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connexion or to case the last accepted term version is uptodate.","title":"Global state"},{"location":"ecolyo/functionalities/usage_events_tracking/","text":"Usage events tracking This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Usage events collection During the use of the application we stored some events link to an user action. Here are the list of collected usage events: Category Type Target Result Context Description Connection ConnectionEvent \"desktop\" or \"mobile\" User connects to the application. Navigation NavigationEvent Page_name User navigates to a targeted page. Konnector KonnectorConnectEvent Konnector_slug \"success\" or \"error\" User connects a konnector. Konnector KonnectorRefreshEvent Konnector_slug \"success\" or \"error\" User refreshes a konnector. Challenge ChallengeLaunchEvent Challenge_id User launches a challenge. Challenge ChallengeEndEvent Challenge_id User ends a challenge. Duel DuelLaunchEvent Duel_id Challenge_id User launches a duel. Duel DuelEndEvent Duel_id Challenge_id User ends a duel. Quiz QuizEndEvent Quiz_id starsNumber Challenge_id User ends a quiz. Exploration ExplorationEndEvent Exploration_id Challenge_id User ends an exploration. Action ActionChangeEvent Action_id Challenge_id User change action's ecogesture. Action ActionEndEvent Action_id Challenge_id User ends a action. Profile ProfileSetEvent User fills in its profile. Consumption ConsumptionCompareEvent Fluid / TimeStep User compares its consumption. Consumption ConsumptionChangeTimeStepEvent TimeStep Fluid User changes timeStep of its consumption. Consumption ConsumptionInteracteEvent Fluid / TimeStep User selects a consumption on the chart. All events are stored with the aggregated flag to false to allow the identification of new events. Usage events aggregator service Functionnalities The service will retrieve all new events by filter on the aggregated flag to false and the event date before than today. For each aggregator type we will defined the right calculation to apply to create the appropriate indicator: calculation of the session time indicator based on ConnectionEvent calculation of the konnectors connected per day based on the fluidStatus calculates if a user launched a duel just after earned 15 stars calculation of the period between 2 different challenges based on the ChallengeLaunchEvent calculation of the period between the first connection and the first challenge based on ChallengeLaunchEvent and ConnectionEvent calculation of an indicator based on a single event calculation of an aggregated indicator to sum an event type per days. Once the indicators is calculated we will: post the indicator to the remote doctype push the event used to calculate the indicator to a array, which will be used to identify all events taken into account during the process. At the end of the service, the service will change the aggregated flag to true for all events present in the array. More technical information are available here Remote doctype All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. Here are the actual structure of this remote doctype: { source: string name: string startDate: string endDate: string value?: number groups: { [key: string]: string } } with: source: contains \"ecolyo\" value. name: contains the indicator type startDate and endDate: used to defined a period or if not relevant, it contains both the date of the events. value: contains aggreated value (example: number of page viewed on a day). groups: contains all other attribute useful for the indicator (example: context, target, result)","title":"Usage events tracking"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-tracking","text":"This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType.","title":"Usage events tracking"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-collection","text":"During the use of the application we stored some events link to an user action. Here are the list of collected usage events: Category Type Target Result Context Description Connection ConnectionEvent \"desktop\" or \"mobile\" User connects to the application. Navigation NavigationEvent Page_name User navigates to a targeted page. Konnector KonnectorConnectEvent Konnector_slug \"success\" or \"error\" User connects a konnector. Konnector KonnectorRefreshEvent Konnector_slug \"success\" or \"error\" User refreshes a konnector. Challenge ChallengeLaunchEvent Challenge_id User launches a challenge. Challenge ChallengeEndEvent Challenge_id User ends a challenge. Duel DuelLaunchEvent Duel_id Challenge_id User launches a duel. Duel DuelEndEvent Duel_id Challenge_id User ends a duel. Quiz QuizEndEvent Quiz_id starsNumber Challenge_id User ends a quiz. Exploration ExplorationEndEvent Exploration_id Challenge_id User ends an exploration. Action ActionChangeEvent Action_id Challenge_id User change action's ecogesture. Action ActionEndEvent Action_id Challenge_id User ends a action. Profile ProfileSetEvent User fills in its profile. Consumption ConsumptionCompareEvent Fluid / TimeStep User compares its consumption. Consumption ConsumptionChangeTimeStepEvent TimeStep Fluid User changes timeStep of its consumption. Consumption ConsumptionInteracteEvent Fluid / TimeStep User selects a consumption on the chart. All events are stored with the aggregated flag to false to allow the identification of new events.","title":"Usage events collection"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-aggregator-service","text":"","title":"Usage events aggregator service"},{"location":"ecolyo/functionalities/usage_events_tracking/#functionnalities","text":"The service will retrieve all new events by filter on the aggregated flag to false and the event date before than today. For each aggregator type we will defined the right calculation to apply to create the appropriate indicator: calculation of the session time indicator based on ConnectionEvent calculation of the konnectors connected per day based on the fluidStatus calculates if a user launched a duel just after earned 15 stars calculation of the period between 2 different challenges based on the ChallengeLaunchEvent calculation of the period between the first connection and the first challenge based on ChallengeLaunchEvent and ConnectionEvent calculation of an indicator based on a single event calculation of an aggregated indicator to sum an event type per days. Once the indicators is calculated we will: post the indicator to the remote doctype push the event used to calculate the indicator to a array, which will be used to identify all events taken into account during the process. At the end of the service, the service will change the aggregated flag to true for all events present in the array. More technical information are available here","title":"Functionnalities"},{"location":"ecolyo/functionalities/usage_events_tracking/#remote-doctype","text":"All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. Here are the actual structure of this remote doctype: { source: string name: string startDate: string endDate: string value?: number groups: { [key: string]: string } } with: source: contains \"ecolyo\" value. name: contains the indicator type startDate and endDate: used to defined a period or if not relevant, it contains both the date of the events. value: contains aggreated value (example: number of page viewed on a day). groups: contains all other attribute useful for the indicator (example: context, target, result)","title":"Remote doctype"},{"location":"ecolyo/getting_started/launch_local_application/","text":"This section will allow you to launch a proper local environment of the Ecolyo application Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo.git Installation of the project Installation of node modules To install required node module, open a terminal on the root folder of the project and type the following command: yarn install Start Ecolyo application To start ecolyo application just launch the command: yarn start If the application starts successfully you should obtain the following message: App successfully compiled! Dev assets:http://localhost:8888 Once the application is started, run the easy-cozy stack with docker. Run easy-cozy dev stack The dev stack will contain the cozy-stack with some default applications and konnectors and allow you to run this stack locally. First login to the forge registry: docker login registry.forge.grandlyon.com You will need to enter for credentials. Next pull the last image of the dev stack: docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env:latest On windows Launch the stack with the following command: yarn winstack A Powershell window will open. Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url: Cozy local url Local database can also be consulted at the following url: Cozy local DB On Linux From the project folder, launch following command: yarn linuxstack Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '. Local database can also be consulted at the following url: Cozy local DB Import mock data Requirement Your dev stack should be running to import the moke data First install ACH using yarn : yarn global add cozy-ach Next create the \"config.js\" file base on the \"config.template.js\" You can change the period of data generated by changing the following lines: const startingdate = DateTime.local() .plus({ days: -120 }) .startOf('day') const endingDate = DateTime.local() .plus({ days: -1 }) .startOf('day') Just replace -120 by the value needed Next launch the script createDayDataFiles.js available into the scripts folder cd scripts node createDayDataFiles.js Json files with data will be created into scripts/data folder. ACH script \"importData.bat\" will load the content of the file into your couchDB (database of your dev stack). Launch it using following commands: cd scripts ./importData.bat If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin . You'll be prompted for a cozysessid, you can get it in the web console ; in the application tab, look for the cookies and just copy the cozysessid value. A new browser windows will open and asking you approval to import data. Just click on Approve Finally your data is loaded in the Ecolyo Application ! Simulate konnectors connection Requirement Your dev stack should be running to import data needed to simulate konnectors connection When using local environment, konnectors are not able to connect. To simulate the connection you can use the script createConnection.js available in scripts folder. First update the authorization and cookie information from the \"config.js\" file (if not created just create it from the \"config.template.js\" file): const authorization = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' To obtain your own Bearer and cozysessid you need to have the application launched and display the web console (F12) in your navigator and select the Network tab. Just select one request and retrieve information for Request Header: Next launch the script : cd scripts node createConnections.js Your data is now loaded and you can refresh the application to see your konnector connected.","title":"Launch the application on local"},{"location":"ecolyo/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"ecolyo/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo.git","title":"Clone the project repository"},{"location":"ecolyo/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"ecolyo/getting_started/launch_local_application/#installation-of-node-modules","text":"To install required node module, open a terminal on the root folder of the project and type the following command: yarn install","title":"Installation of node modules"},{"location":"ecolyo/getting_started/launch_local_application/#start-ecolyo-application","text":"To start ecolyo application just launch the command: yarn start If the application starts successfully you should obtain the following message: App successfully compiled! Dev assets:http://localhost:8888 Once the application is started, run the easy-cozy stack with docker.","title":"Start Ecolyo application"},{"location":"ecolyo/getting_started/launch_local_application/#run-easy-cozy-dev-stack","text":"The dev stack will contain the cozy-stack with some default applications and konnectors and allow you to run this stack locally. First login to the forge registry: docker login registry.forge.grandlyon.com You will need to enter for credentials. Next pull the last image of the dev stack: docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env:latest","title":"Run easy-cozy dev stack"},{"location":"ecolyo/getting_started/launch_local_application/#on-windows","text":"Launch the stack with the following command: yarn winstack A Powershell window will open. Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url: Cozy local url Local database can also be consulted at the following url: Cozy local DB","title":"On windows"},{"location":"ecolyo/getting_started/launch_local_application/#on-linux","text":"From the project folder, launch following command: yarn linuxstack Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '. Local database can also be consulted at the following url: Cozy local DB","title":"On Linux"},{"location":"ecolyo/getting_started/launch_local_application/#import-mock-data","text":"Requirement Your dev stack should be running to import the moke data First install ACH using yarn : yarn global add cozy-ach Next create the \"config.js\" file base on the \"config.template.js\" You can change the period of data generated by changing the following lines: const startingdate = DateTime.local() .plus({ days: -120 }) .startOf('day') const endingDate = DateTime.local() .plus({ days: -1 }) .startOf('day') Just replace -120 by the value needed Next launch the script createDayDataFiles.js available into the scripts folder cd scripts node createDayDataFiles.js Json files with data will be created into scripts/data folder. ACH script \"importData.bat\" will load the content of the file into your couchDB (database of your dev stack). Launch it using following commands: cd scripts ./importData.bat If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin . You'll be prompted for a cozysessid, you can get it in the web console ; in the application tab, look for the cookies and just copy the cozysessid value. A new browser windows will open and asking you approval to import data. Just click on Approve Finally your data is loaded in the Ecolyo Application !","title":"Import mock data"},{"location":"ecolyo/getting_started/launch_local_application/#simulate-konnectors-connection","text":"Requirement Your dev stack should be running to import data needed to simulate konnectors connection When using local environment, konnectors are not able to connect. To simulate the connection you can use the script createConnection.js available in scripts folder. First update the authorization and cookie information from the \"config.js\" file (if not created just create it from the \"config.template.js\" file): const authorization = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' To obtain your own Bearer and cozysessid you need to have the application launched and display the web console (F12) in your navigator and select the Network tab. Just select one request and retrieve information for Request Header: Next launch the script : cd scripts node createConnections.js Your data is now loaded and you can refresh the application to see your konnector connected.","title":"Simulate konnectors connection"},{"location":"ecolyo/getting_started/launch_local_konnector/","text":"Cozy ressources Please see also the official cozy documentation . Run a konnector locally To develop a konnector or test it, you will need to be able to run a konnector without the constraints imposed by the cozy stack. To help you, cozy developped a standalone mode for konnectors. Simply launch it by typing: yarn standalone This command will create a konnector-dev-config.json file if it was not in your project folder before. This file needs to hold all the informations transmitted by the cozy stack when the konnector runs by default baseUrl apiAuthKey login password and so on... Type them all in the fields object. All data recovered by the standalone konnector will be stored in the data folder.","title":"Launch a konnector on local"},{"location":"ecolyo/getting_started/launch_local_konnector/#cozy-ressources","text":"Please see also the official cozy documentation .","title":"Cozy ressources"},{"location":"ecolyo/getting_started/launch_local_konnector/#run-a-konnector-locally","text":"To develop a konnector or test it, you will need to be able to run a konnector without the constraints imposed by the cozy stack. To help you, cozy developped a standalone mode for konnectors. Simply launch it by typing: yarn standalone This command will create a konnector-dev-config.json file if it was not in your project folder before. This file needs to hold all the informations transmitted by the cozy stack when the konnector runs by default baseUrl apiAuthKey login password and so on... Type them all in the fields object. All data recovered by the standalone konnector will be stored in the data folder.","title":"Run a konnector locally"},{"location":"ecolyo/project_architecture/architecture/","text":"Architecture Principle diagram The principle diagram below describes the responsibilities of each application brick.","title":"Architecture"},{"location":"ecolyo/project_architecture/architecture/#architecture","text":"","title":"Architecture"},{"location":"ecolyo/project_architecture/architecture/#principle-diagram","text":"The principle diagram below describes the responsibilities of each application brick.","title":"Principle diagram"},{"location":"ecolyo/project_architecture/doctypes/","text":"Timeseries doctypes Description Each fluid has its own doctype wildcard and one doctype per time step. Each available time step for a fluid depends of the available data from the energy provider. Here are the different time step: half an hour - use com.grandlyon.*.minute doctype week - use com.grandlyon.*.day doctype day - use com.grandlyon.*.day doctype month - use com.grandlyon.*.month doctype year - use com.grandlyon.*.year doctype Doctype Here are the available doctypes: Fluid type Doctype wildcard Doctypes electricity fluid / enedis com.grandlyon.enedis.* com.grandlyon.enedis.minute com.grandlyon.enedis.day com.grandlyon.enedis.month com.grandlyon.enedis.year gaz fluid / grdf com.grandlyon.grdf.* com.grandlyon.grdf.day com.grandlyon.grdf.month com.grandlyon.grdf.year water fluid / eau du grand lyon com.grandlyon.egl.* com.grandlyon.egl.day com.grandlyon.egl.month com.grandlyon.egl.year Structure Field Type Description load number load (in kWh or L) minute number minute of the date set to 0 except for minute serie hour number hour of the date set to 0 except for minute and hour series day number day of the date set to 1 for month and year series month number month of the date set to 1 for year series year number year of the date Example { \"load\": 770.18, \"minute\": 0, \"hour\": 0, \"day\": 1, \"month\": 1, \"year\": 2020 } User profile Description This doctype is used to store all information about the user. Doctype com.grandlyon.ecolyo.profile Structure Field Type Description id string Profile id ecogestureHash string Hash used to verify the content of ecogestures challengeHash string Hash used to verify the content of challenges duelHash string Hash used to verify the content of duels quizHash string Hash used to verify the content of quiz explorationHash string Hash used to verify the content of exploration isFirstConnection boolean Boolean used to inform if the user connects for the first time lastConnectionDate DateTime Date of the last user connection haveSeenLastAnalysis boolean Boolean used to inform if user has seen the last analysis haveSeenOldFluidModal Datetime or boolean Used to inform if user has seen the modal display when his data are too old. Its value is false or a DateTime when he saw it sendAnalysisNotification boolean Boolean used to inform if user has seen the analysis notification monthlyAnalysisDate DateTime Date of the last monthly analysis profileType ProfileType User consumption profile isProfileTypeCompleted boolean Check if a user has completed his consumption profile showConsentModal boolean Boolean used to show the terms acceptation page, and to protect the app private routes if last terms are not accepted or outdated Example { \"id\": \"0e016e853592e18155e87b85ce00a33a\", \"challengeHash\": \"4cbcafe514788757c377534f1a407e022c29e38c\", \"duelHash\": \"48371ffabb2853b0503b882f11e1fa8e730bac76\", \"ecogestureHash\": \"9798a0aaccb47cff906fc4931a2eff5f9371dd8b\", \"haveSeenLastAnalysis\": true, \"haveSeenOldFluidModal\": false, \"isFirstConnection\": false, \"lastConnectionDate\": \"2021-03-08T17:33:18.727Z\", \"monthlyAnalysisDate\": \"2021-01-03T00:00:00.000+01:00\", \"quizHash\": \"11372a56c03edef1d6656f8a76d5ec457174f2c1\", \"explorationHash\": \"cdbc7a84d041318253a10b3cc0c02f9020c78c0b\", \"sendAnalysisNotification\": false, \"profileType\": { \"area\": \"123\", \"coldWater\": \"individual\", \"constructionYear\": \"between_1948_and_1974\", \"cookingFluid\": 0, \"floor\": \"not_applicable\", \"hasInstalledVentilation\": \"yes\", \"hasReplacedHeater\": \"yes\", \"heating\": \"individual\", \"hotWater\": \"individual\", \"hotWaterEquipment\": \"solar\", \"hotWaterFluid\": 0, \"housingType\": \"individual_house\", \"individualInsulationWork\": [ \"roof_insulation\" ], \"occupantsNumber\": 1, \"outsideFacingWalls\": \"2\", \"warmingFluid\": 0 }, \"isProfileTypeCompleted\": true, \"showConsentModal\": true } Ecogesture Description This doctype is used to store ecogestures. Doctype com.grandlyon.ecolyo.ecogesture Structure Field Type Description id string ecogesture id shortName string short name of the ecogesture longName string long name of the ecogesture longDescription string long description of the ecogesture usage Usage usage of the ecogesture Usage enum: - ALL = 0 - HEATING = 1 - AIR_CONDITIONING = 2 - ECS = 3 - COLD_WATER = 4 - ELECTRICITY_SPECIFIC = 5 - COOKING = 6 fluidTypes FluidType[] Array of fluid type on which ecogesture can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 impactLevel number impact level of the ecogesture efficiency number efficiency of the ecogesture difficulty number difficulty of the ecogesture room Room room affected by the ecogesture Room enum: - ALL = 0 - BATHROOM = 1 - KITCHEN = 2 - LAUNDRY = 3 - TOILET = 4 season Season season suited to the ecogesture Season enum: - NONE = 'Sans saison' - WINTER = 'Hiver' - SUMMER = 'Et\u00e9' equipment boolean used to know if one or more equipment are affected by the ecogesture equipmentType EquipmentType[] equipment affected by the ecogesture EquipmentType enum: - AIR_CONDITIONING = 0 - COMPUTER = 1 - MICROWAVE = 2 - OVEN = 3 - WASHING_MACHINE = 4 - DISHWASHER = 5 - COOKING_PLATES = 6 - DRYER = 7 - REFREGIRATOR = 8 - GARDEN = 9 - WATER_HEATER = 10 - FAN = 11 - CURTAIN = 12 - INTERNET_BOX = 13 - VENTILATION = 14 - FREEZER = 15 - BOILER = 16 - HYDRAULIC_HEATING = 17 equipmentInstallation boolean used to know if it is required an installation investment string or null investment required action boolean used to know if the ecogesture is used for action challenge actionName string or null action description of the ecogesture actionDuration number duration required to do an action challenge Example { \"shortName\": \"D\u00e9esse des eaux\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"usage\": 3, \"fluidTypes\": [ 1 ], \"impactLevel\": 5, \"investment\": null, \"room\": [ 1 ], \"difficulty\": 1, \"efficiency\": 4, \"season\": \"Sans saison\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], } Challenge Description This doctype is used to store all challenges. Doctype com.grandlyon.ecolyo.challenge Structure Field Type Description _id string challenge id - respect the format CHALLENGE000X title string title of the challenge description string description of the challenge target number The number of stars required to unlock the duel relationships any relation to quiz and duel Example { \"_id\": \"CHALLENGE0001\", \"title\": \"Nicolas Hublot\", \"description\": \"foobar\", \"target\": 15, \"relationships\": { \"quiz\": { \"data\": { \"_id\": \"QUIZ001\", \"_type\": \"com.grandlyon.ecolyo.quiz\" } }, \"exploration\": { \"data\": { \"_id\": \"EXPLORATION001\", \"_type\": \"com.grandlyon.ecolyo.exploration\" } }, \"duel\": { \"data\": { \"_id\": \"DUEL001\", \"_type\": \"com.grandlyon.ecolyo.duel\" } } } } User challenge Description This doctype is used to store all additionnal information about a challenge started or ended by the user. Doctype com.grandlyon.ecolyo.userchallenge Structure Field Type Description id string userChallenge id title string userChallenge title state UserChallengeState state of the challenge UserChallengeState enum - LOCKED = 0 - UNLOCKED = 1 - ONGOING = 2 - DUEL = 3 - DONE = 4 target number Number of stars required to unlock the duel progress ChallengeProgress Number of stars earned by the user for each challenge ChallengeProgress enum - quizzProgress: number - explorationProgress: number - actionProgress: number quiz UserQuiz Complete Quiz object with progress exploration UserExploration Complete Exploration object with progress action UserActionEntity Complete Action object duel UserDuelEntity Complete Duel object with progress included success UserChallengeSuccess Success state of the challenge UserChallengeSuccess enum - ONGOING = 0 - LOST = 1 - WIN = 2 startDate string null starting date of the the challenge endingDate string null ending date of the challenge Example { \"_id\": \"eae3a79a05d677a739bdd2b46b009936\", \"description\": \"foobar\", \"duel\": { \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 }, \"fluidTypes\": [ 0, 1, 2 ], \"id\": \"DUEL001\", \"startDate\": null, \"state\": 4, \"threshold\": -1, \"title\": \"Nicolas Hublot\", \"userConsumption\": 0 }, \"endingDate\": null, \"id\": \"CHALLENGE0001\", \"progress\": { \"actionProgress\": 0, \"explorationProgress\": 0, \"quizProgress\": 0 }, \"quiz\": { \"customQuestion\": { \"interval\": 30, \"period\": {}, \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"result\": 1, \"timeStep\": 20, \"type\": 0 }, \"id\": \"QUIZ001\", \"questions\": [ { \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"result\": 1, \"source\": \"string\" } ], \"result\": 5, \"state\": 2 }, \"exploration\": { \"id\": \"EXPLORATION001\", \"date\": \"2021-01-13T17:03:11.964Z\", \"description\": \"Consultez 3 fois Ecolyo\", \"ecogesture_id\": \"\", \"fluid_condition\": [], \"message_success\": \"Vous vous \u00eates connect\u00e9 3 fois \u00e0 Ecolyo\", \"progress\": 0, \"state\": 2, \"target\": 3, \"type\": 2 }, \"action\": { \"ecogesture\": { \"_id\": \"ECOGESTURE0004\", \"_rev\": \"3-da2ad5c7b81e4260e2254c98ec6ee971\", \"_type\": \"com.grandlyon.ecolyo.ecogesture\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"cozyMetadata\": { \"createdAt\": \"2021-03-08T09:52:41.029Z\", \"createdByApp\": \"Ecolyo\", \"createdByAppVersion\": \"1.0.4\", \"metadataVersion\": 1, \"updatedAt\": \"2021-03-08T09:52:41.029Z\", \"updatedByApps\": [ { \"date\": \"2021-03-08T09:52:41.029Z\", \"slug\": \"Ecolyo\", \"version\": \"1.0.4\" } ] }, \"difficulty\": 1, \"efficiency\": 2.5, \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], \"fluidTypes\": [ 1 ], \"id\": \"ECOGESTURE0004\", \"impactLevel\": 5, \"investment\": null, \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"room\": [ 1 ], \"season\": \"Sans saison\", \"shortName\": \"D\u00e9esse des eaux\", \"usage\": 3 }, \"startDate\": \"2021-03-09T17:57:44.600Z\", \"state\": 1 }, \"startDate\": \"2021-01-04T00:00:00.000Z\", \"state\": 3, \"success\": 0, \"target\": 15, \"title\": \"Nicolas Hublot\" } Quiz Description This doctype is used to store all quiz. Doctype com.grandlyon.ecolyo.quiz Structure Field Type Description _id string quiz id - respect the format QUIZ00X questions QuestionEntity[] Array of questions entities customQuestion CustomQuestionEntity Custom question based on user's consumption Example { \"_id\": \"QUIZ001\", \"questions\": [ { \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"source\": \"string\" }, { \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"source\": \"string\" } ], \"customQuestion\": { \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"type\": 0, \"timeStep\": 20, \"interval\": 30, \"period\": {}, \"singleFluid\": true } } Exploration Description This doctype is used to store all explorations. Doctype com.grandlyon.ecolyo.exploration Structure Field Type Description _id string exploration id - respect the format EXPLORATION00X state UserExplorationState State of the exploration UserExplorationState enum - UNLOCKED = 0 - ONGOING = 1 - DONE = 2 description string description of the exploration target number number of stars required to unlock an exploration type UserExplorationType type of the exploration UserExplorationType enum - DECLARATIVE = 0 - ACTION = 1 - CONSUMPTION = 2 - ECOGESTURE = 3 date string or null date of the exploration ecogesture_id string ecogesture's id fluid_condition FluidType[] Array of fluid type on which an exploration can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 message_success string message when exploration is done Example { \"_id\": \"EXPLORATION001\", \"description\": \"Consultez l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"target\": 1, \"type\": 3, \"date\": null, \"ecogesture_id\": \"0032\", \"fluid_condition\": [], \"message_success\": \"Vous avez consult\u00e9 l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"state\": 0, } Duel Description This doctype is used to store all duels. Doctype com.grandlyon.ecolyo.duel Structure Field Type Description _id string duel id - respect the format DUEL00X title string title of the duel description string description of the duel duration Duration Luxon Duration of the duel Example { \"_id\": \"DUEL001\", \"title\": \"Nicolas Hublot\", \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 } } Usage event Description This doctype is used to store all usage events. Doctype com.grandlyon.ecolyo.usageevent Structure Field Type Description date DateTime Date of the event type UsageEventType Type of the event target string Targeted konnector, page, challenge, quiz, exploration, action or timeStep result string Result for KonnectorConnectEvent or KonnectorRefreshEvent. Values: \"success\" or \"error\" context string Luxon Duration of the duel Terms Description This doctype is used to store the different version of the terms of the application. Doctype io.cozy.terms Structure Field Type Description accepted boolean The fact that the terms has been accepted by the Cozy user or not acceptedAt DateTime The date when the Cozy user accepted these terms termsId string The id of the terms version string The version number MaxPower Description This doctype is used to store the enedis maxpower values retrieved by the konnector on a daily basis. The value is in kVA. Doctype com.grandlyon.enedis.maxpower Structure Field Type Description load number maxPower in kVA minute number minute of the date hour number hour of the date day number day of the date month number month of the date year number year of the date Enedis Monthly Analysis Data Description This doctype is used to store the enedis monthly analysis, it includes the month average half-hour consumption for weekdays and weekends, the minimum half-hour load, and the max power consumption of the month. Doctype com.grandlyon.enedis.monthly.analysis.data Structure Field Type Description weekDaysHalfHourAverageValues number[] Half-hour average value for week days (monday to friday) weekEndDaysHalfHourAverageValues number[] Half-hour average value for weekend days (saturday and sunday) month number Month of the analysis year number Year of the analysis minLoad number or null Minimum half hour load of the month maxPower number or null Max power value of the month","title":"DocTypes"},{"location":"ecolyo/project_architecture/doctypes/#timeseries-doctypes","text":"","title":"Timeseries doctypes"},{"location":"ecolyo/project_architecture/doctypes/#description","text":"Each fluid has its own doctype wildcard and one doctype per time step. Each available time step for a fluid depends of the available data from the energy provider. Here are the different time step: half an hour - use com.grandlyon.*.minute doctype week - use com.grandlyon.*.day doctype day - use com.grandlyon.*.day doctype month - use com.grandlyon.*.month doctype year - use com.grandlyon.*.year doctype","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype","text":"Here are the available doctypes: Fluid type Doctype wildcard Doctypes electricity fluid / enedis com.grandlyon.enedis.* com.grandlyon.enedis.minute com.grandlyon.enedis.day com.grandlyon.enedis.month com.grandlyon.enedis.year gaz fluid / grdf com.grandlyon.grdf.* com.grandlyon.grdf.day com.grandlyon.grdf.month com.grandlyon.grdf.year water fluid / eau du grand lyon com.grandlyon.egl.* com.grandlyon.egl.day com.grandlyon.egl.month com.grandlyon.egl.year","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure","text":"Field Type Description load number load (in kWh or L) minute number minute of the date set to 0 except for minute serie hour number hour of the date set to 0 except for minute and hour series day number day of the date set to 1 for month and year series month number month of the date set to 1 for year series year number year of the date","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example","text":"{ \"load\": 770.18, \"minute\": 0, \"hour\": 0, \"day\": 1, \"month\": 1, \"year\": 2020 }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#user-profile","text":"","title":"User profile"},{"location":"ecolyo/project_architecture/doctypes/#description_1","text":"This doctype is used to store all information about the user.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_1","text":"com.grandlyon.ecolyo.profile","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_1","text":"Field Type Description id string Profile id ecogestureHash string Hash used to verify the content of ecogestures challengeHash string Hash used to verify the content of challenges duelHash string Hash used to verify the content of duels quizHash string Hash used to verify the content of quiz explorationHash string Hash used to verify the content of exploration isFirstConnection boolean Boolean used to inform if the user connects for the first time lastConnectionDate DateTime Date of the last user connection haveSeenLastAnalysis boolean Boolean used to inform if user has seen the last analysis haveSeenOldFluidModal Datetime or boolean Used to inform if user has seen the modal display when his data are too old. Its value is false or a DateTime when he saw it sendAnalysisNotification boolean Boolean used to inform if user has seen the analysis notification monthlyAnalysisDate DateTime Date of the last monthly analysis profileType ProfileType User consumption profile isProfileTypeCompleted boolean Check if a user has completed his consumption profile showConsentModal boolean Boolean used to show the terms acceptation page, and to protect the app private routes if last terms are not accepted or outdated","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_1","text":"{ \"id\": \"0e016e853592e18155e87b85ce00a33a\", \"challengeHash\": \"4cbcafe514788757c377534f1a407e022c29e38c\", \"duelHash\": \"48371ffabb2853b0503b882f11e1fa8e730bac76\", \"ecogestureHash\": \"9798a0aaccb47cff906fc4931a2eff5f9371dd8b\", \"haveSeenLastAnalysis\": true, \"haveSeenOldFluidModal\": false, \"isFirstConnection\": false, \"lastConnectionDate\": \"2021-03-08T17:33:18.727Z\", \"monthlyAnalysisDate\": \"2021-01-03T00:00:00.000+01:00\", \"quizHash\": \"11372a56c03edef1d6656f8a76d5ec457174f2c1\", \"explorationHash\": \"cdbc7a84d041318253a10b3cc0c02f9020c78c0b\", \"sendAnalysisNotification\": false, \"profileType\": { \"area\": \"123\", \"coldWater\": \"individual\", \"constructionYear\": \"between_1948_and_1974\", \"cookingFluid\": 0, \"floor\": \"not_applicable\", \"hasInstalledVentilation\": \"yes\", \"hasReplacedHeater\": \"yes\", \"heating\": \"individual\", \"hotWater\": \"individual\", \"hotWaterEquipment\": \"solar\", \"hotWaterFluid\": 0, \"housingType\": \"individual_house\", \"individualInsulationWork\": [ \"roof_insulation\" ], \"occupantsNumber\": 1, \"outsideFacingWalls\": \"2\", \"warmingFluid\": 0 }, \"isProfileTypeCompleted\": true, \"showConsentModal\": true }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#ecogesture","text":"","title":"Ecogesture"},{"location":"ecolyo/project_architecture/doctypes/#description_2","text":"This doctype is used to store ecogestures.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_2","text":"com.grandlyon.ecolyo.ecogesture","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_2","text":"Field Type Description id string ecogesture id shortName string short name of the ecogesture longName string long name of the ecogesture longDescription string long description of the ecogesture usage Usage usage of the ecogesture Usage enum: - ALL = 0 - HEATING = 1 - AIR_CONDITIONING = 2 - ECS = 3 - COLD_WATER = 4 - ELECTRICITY_SPECIFIC = 5 - COOKING = 6 fluidTypes FluidType[] Array of fluid type on which ecogesture can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 impactLevel number impact level of the ecogesture efficiency number efficiency of the ecogesture difficulty number difficulty of the ecogesture room Room room affected by the ecogesture Room enum: - ALL = 0 - BATHROOM = 1 - KITCHEN = 2 - LAUNDRY = 3 - TOILET = 4 season Season season suited to the ecogesture Season enum: - NONE = 'Sans saison' - WINTER = 'Hiver' - SUMMER = 'Et\u00e9' equipment boolean used to know if one or more equipment are affected by the ecogesture equipmentType EquipmentType[] equipment affected by the ecogesture EquipmentType enum: - AIR_CONDITIONING = 0 - COMPUTER = 1 - MICROWAVE = 2 - OVEN = 3 - WASHING_MACHINE = 4 - DISHWASHER = 5 - COOKING_PLATES = 6 - DRYER = 7 - REFREGIRATOR = 8 - GARDEN = 9 - WATER_HEATER = 10 - FAN = 11 - CURTAIN = 12 - INTERNET_BOX = 13 - VENTILATION = 14 - FREEZER = 15 - BOILER = 16 - HYDRAULIC_HEATING = 17 equipmentInstallation boolean used to know if it is required an installation investment string or null investment required action boolean used to know if the ecogesture is used for action challenge actionName string or null action description of the ecogesture actionDuration number duration required to do an action challenge","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_2","text":"{ \"shortName\": \"D\u00e9esse des eaux\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"usage\": 3, \"fluidTypes\": [ 1 ], \"impactLevel\": 5, \"investment\": null, \"room\": [ 1 ], \"difficulty\": 1, \"efficiency\": 4, \"season\": \"Sans saison\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#challenge","text":"","title":"Challenge"},{"location":"ecolyo/project_architecture/doctypes/#description_3","text":"This doctype is used to store all challenges.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_3","text":"com.grandlyon.ecolyo.challenge","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_3","text":"Field Type Description _id string challenge id - respect the format CHALLENGE000X title string title of the challenge description string description of the challenge target number The number of stars required to unlock the duel relationships any relation to quiz and duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_3","text":"{ \"_id\": \"CHALLENGE0001\", \"title\": \"Nicolas Hublot\", \"description\": \"foobar\", \"target\": 15, \"relationships\": { \"quiz\": { \"data\": { \"_id\": \"QUIZ001\", \"_type\": \"com.grandlyon.ecolyo.quiz\" } }, \"exploration\": { \"data\": { \"_id\": \"EXPLORATION001\", \"_type\": \"com.grandlyon.ecolyo.exploration\" } }, \"duel\": { \"data\": { \"_id\": \"DUEL001\", \"_type\": \"com.grandlyon.ecolyo.duel\" } } } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#user-challenge","text":"","title":"User challenge"},{"location":"ecolyo/project_architecture/doctypes/#description_4","text":"This doctype is used to store all additionnal information about a challenge started or ended by the user.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_4","text":"com.grandlyon.ecolyo.userchallenge","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_4","text":"Field Type Description id string userChallenge id title string userChallenge title state UserChallengeState state of the challenge UserChallengeState enum - LOCKED = 0 - UNLOCKED = 1 - ONGOING = 2 - DUEL = 3 - DONE = 4 target number Number of stars required to unlock the duel progress ChallengeProgress Number of stars earned by the user for each challenge ChallengeProgress enum - quizzProgress: number - explorationProgress: number - actionProgress: number quiz UserQuiz Complete Quiz object with progress exploration UserExploration Complete Exploration object with progress action UserActionEntity Complete Action object duel UserDuelEntity Complete Duel object with progress included success UserChallengeSuccess Success state of the challenge UserChallengeSuccess enum - ONGOING = 0 - LOST = 1 - WIN = 2 startDate string null starting date of the the challenge endingDate string null ending date of the challenge","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_4","text":"{ \"_id\": \"eae3a79a05d677a739bdd2b46b009936\", \"description\": \"foobar\", \"duel\": { \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 }, \"fluidTypes\": [ 0, 1, 2 ], \"id\": \"DUEL001\", \"startDate\": null, \"state\": 4, \"threshold\": -1, \"title\": \"Nicolas Hublot\", \"userConsumption\": 0 }, \"endingDate\": null, \"id\": \"CHALLENGE0001\", \"progress\": { \"actionProgress\": 0, \"explorationProgress\": 0, \"quizProgress\": 0 }, \"quiz\": { \"customQuestion\": { \"interval\": 30, \"period\": {}, \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"result\": 1, \"timeStep\": 20, \"type\": 0 }, \"id\": \"QUIZ001\", \"questions\": [ { \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"result\": 1, \"source\": \"string\" } ], \"result\": 5, \"state\": 2 }, \"exploration\": { \"id\": \"EXPLORATION001\", \"date\": \"2021-01-13T17:03:11.964Z\", \"description\": \"Consultez 3 fois Ecolyo\", \"ecogesture_id\": \"\", \"fluid_condition\": [], \"message_success\": \"Vous vous \u00eates connect\u00e9 3 fois \u00e0 Ecolyo\", \"progress\": 0, \"state\": 2, \"target\": 3, \"type\": 2 }, \"action\": { \"ecogesture\": { \"_id\": \"ECOGESTURE0004\", \"_rev\": \"3-da2ad5c7b81e4260e2254c98ec6ee971\", \"_type\": \"com.grandlyon.ecolyo.ecogesture\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"cozyMetadata\": { \"createdAt\": \"2021-03-08T09:52:41.029Z\", \"createdByApp\": \"Ecolyo\", \"createdByAppVersion\": \"1.0.4\", \"metadataVersion\": 1, \"updatedAt\": \"2021-03-08T09:52:41.029Z\", \"updatedByApps\": [ { \"date\": \"2021-03-08T09:52:41.029Z\", \"slug\": \"Ecolyo\", \"version\": \"1.0.4\" } ] }, \"difficulty\": 1, \"efficiency\": 2.5, \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], \"fluidTypes\": [ 1 ], \"id\": \"ECOGESTURE0004\", \"impactLevel\": 5, \"investment\": null, \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"room\": [ 1 ], \"season\": \"Sans saison\", \"shortName\": \"D\u00e9esse des eaux\", \"usage\": 3 }, \"startDate\": \"2021-03-09T17:57:44.600Z\", \"state\": 1 }, \"startDate\": \"2021-01-04T00:00:00.000Z\", \"state\": 3, \"success\": 0, \"target\": 15, \"title\": \"Nicolas Hublot\" }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#quiz","text":"","title":"Quiz"},{"location":"ecolyo/project_architecture/doctypes/#description_5","text":"This doctype is used to store all quiz.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_5","text":"com.grandlyon.ecolyo.quiz","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_5","text":"Field Type Description _id string quiz id - respect the format QUIZ00X questions QuestionEntity[] Array of questions entities customQuestion CustomQuestionEntity Custom question based on user's consumption","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_5","text":"{ \"_id\": \"QUIZ001\", \"questions\": [ { \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"source\": \"string\" }, { \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"source\": \"string\" } ], \"customQuestion\": { \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"type\": 0, \"timeStep\": 20, \"interval\": 30, \"period\": {}, \"singleFluid\": true } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#exploration","text":"","title":"Exploration"},{"location":"ecolyo/project_architecture/doctypes/#description_6","text":"This doctype is used to store all explorations.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_6","text":"com.grandlyon.ecolyo.exploration","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_6","text":"Field Type Description _id string exploration id - respect the format EXPLORATION00X state UserExplorationState State of the exploration UserExplorationState enum - UNLOCKED = 0 - ONGOING = 1 - DONE = 2 description string description of the exploration target number number of stars required to unlock an exploration type UserExplorationType type of the exploration UserExplorationType enum - DECLARATIVE = 0 - ACTION = 1 - CONSUMPTION = 2 - ECOGESTURE = 3 date string or null date of the exploration ecogesture_id string ecogesture's id fluid_condition FluidType[] Array of fluid type on which an exploration can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 message_success string message when exploration is done","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_6","text":"{ \"_id\": \"EXPLORATION001\", \"description\": \"Consultez l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"target\": 1, \"type\": 3, \"date\": null, \"ecogesture_id\": \"0032\", \"fluid_condition\": [], \"message_success\": \"Vous avez consult\u00e9 l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"state\": 0, }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#duel","text":"","title":"Duel"},{"location":"ecolyo/project_architecture/doctypes/#description_7","text":"This doctype is used to store all duels.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_7","text":"com.grandlyon.ecolyo.duel","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_7","text":"Field Type Description _id string duel id - respect the format DUEL00X title string title of the duel description string description of the duel duration Duration Luxon Duration of the duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_7","text":"{ \"_id\": \"DUEL001\", \"title\": \"Nicolas Hublot\", \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#usage-event","text":"","title":"Usage event"},{"location":"ecolyo/project_architecture/doctypes/#description_8","text":"This doctype is used to store all usage events.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_8","text":"com.grandlyon.ecolyo.usageevent","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_8","text":"Field Type Description date DateTime Date of the event type UsageEventType Type of the event target string Targeted konnector, page, challenge, quiz, exploration, action or timeStep result string Result for KonnectorConnectEvent or KonnectorRefreshEvent. Values: \"success\" or \"error\" context string Luxon Duration of the duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#terms","text":"","title":"Terms"},{"location":"ecolyo/project_architecture/doctypes/#description_9","text":"This doctype is used to store the different version of the terms of the application.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_9","text":"io.cozy.terms","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_9","text":"Field Type Description accepted boolean The fact that the terms has been accepted by the Cozy user or not acceptedAt DateTime The date when the Cozy user accepted these terms termsId string The id of the terms version string The version number","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#maxpower","text":"","title":"MaxPower"},{"location":"ecolyo/project_architecture/doctypes/#description_10","text":"This doctype is used to store the enedis maxpower values retrieved by the konnector on a daily basis. The value is in kVA.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_10","text":"com.grandlyon.enedis.maxpower","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_10","text":"Field Type Description load number maxPower in kVA minute number minute of the date hour number hour of the date day number day of the date month number month of the date year number year of the date","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#enedis-monthly-analysis-data","text":"","title":"Enedis Monthly Analysis Data"},{"location":"ecolyo/project_architecture/doctypes/#description_11","text":"This doctype is used to store the enedis monthly analysis, it includes the month average half-hour consumption for weekdays and weekends, the minimum half-hour load, and the max power consumption of the month.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_11","text":"com.grandlyon.enedis.monthly.analysis.data","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_11","text":"Field Type Description weekDaysHalfHourAverageValues number[] Half-hour average value for week days (monday to friday) weekEndDaysHalfHourAverageValues number[] Half-hour average value for weekend days (saturday and sunday) month number Month of the analysis year number Year of the analysis minLoad number or null Minimum half hour load of the month maxPower number or null Max power value of the month","title":"Structure"},{"location":"ecolyo/project_architecture/environments/","text":"Environments We have 2 environments available for this project: - One environment of dev hosted on scaleway and managed by the dev team - One environment of production hosted on Cozy and managed by Cozy Dev environment aka alpha The dev environnment has been mounted on a dedicated instance on scaleway. Access to the dev environment You need to install an ssh tool like Putty or MobaXterm in order to connect to the server. Connection to the server is made using ssh key, you need to generate your own and ask administrator to allow your ssh key. Once done, you shoul be able to connect to the server using your private key. Cozy stack It is based on the easy-cozy project available on GitLab: https://forge.grandlyon.com/pocs/cozy/easy-cozy On the server, the .env file has been initialize with the good secrets (see the .env.template) and also initialize to create instance with Ecolyo and the 3 needed konnectors by default. This project will build and run 3 images: - the cozy stack - the couch db - keycloack To run the project please refer to the documentation on the GitLab project. Once the project is up and running, we are able to create, update and delete instances. Let's see more details in the dedicated section . Proxy Konnector for Ecolyo need proxy for the OAuth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy The proxy is written in Go language. The \"main.go\" file containt all the source code and also the default variables. Default variables are the one used for the dev environment but we will overwrite them for the production. To Launch the proxy, just pull the project and use the docker-compose file with following commands: git pull https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy cd cozy-oauth-proxy docker-compose up -d Ecolyo and konnectors By default the version present on the \"build-dev\" branch is used to install Ecolyo app and konnectors on a new instance. Some scripts has been created in order to install, update, downgrade, remove app and konnectors. Please refer to the dedicated section for more information. Prod environment This environment is fully managed by Cozy team. Cozy stack Fully managed by Cozy team. Proxy A dedicated proxy is deployed on Cozy side to allow konnector to make the OAuth dance. The proxy deployed is based on the project available on the GitLab but variables are overwritten using flags by the Cozy team in order to fit to the environment. For each modification in production, it needs: - to be done on the gitLab project - to be testeded in dev environnment After that we should ask Cozy to pull the modification from the GitLab in order to have them in production. Ecolyo and konnectors The production environment is based on the build branch which should reflect the build of sources present on master branch. Each deployment is done manually for each app/konnector by: - building the application (yarn build) - deploy the build on the build branch (yarn deploy) - publishing content of build branch into Cozy repository (yarn cozyPublish) Once it is published, Cozy team should validate it before deploying the new app version into all Cozy Grand Lyon instances.","title":"Environments"},{"location":"ecolyo/project_architecture/environments/#environments","text":"We have 2 environments available for this project: - One environment of dev hosted on scaleway and managed by the dev team - One environment of production hosted on Cozy and managed by Cozy","title":"Environments"},{"location":"ecolyo/project_architecture/environments/#dev-environment-aka-alpha","text":"The dev environnment has been mounted on a dedicated instance on scaleway.","title":"Dev environment aka alpha"},{"location":"ecolyo/project_architecture/environments/#access-to-the-dev-environment","text":"You need to install an ssh tool like Putty or MobaXterm in order to connect to the server. Connection to the server is made using ssh key, you need to generate your own and ask administrator to allow your ssh key. Once done, you shoul be able to connect to the server using your private key.","title":"Access to the dev environment"},{"location":"ecolyo/project_architecture/environments/#cozy-stack","text":"It is based on the easy-cozy project available on GitLab: https://forge.grandlyon.com/pocs/cozy/easy-cozy On the server, the .env file has been initialize with the good secrets (see the .env.template) and also initialize to create instance with Ecolyo and the 3 needed konnectors by default. This project will build and run 3 images: - the cozy stack - the couch db - keycloack To run the project please refer to the documentation on the GitLab project. Once the project is up and running, we are able to create, update and delete instances. Let's see more details in the dedicated section .","title":"Cozy stack"},{"location":"ecolyo/project_architecture/environments/#proxy","text":"Konnector for Ecolyo need proxy for the OAuth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy The proxy is written in Go language. The \"main.go\" file containt all the source code and also the default variables. Default variables are the one used for the dev environment but we will overwrite them for the production. To Launch the proxy, just pull the project and use the docker-compose file with following commands: git pull https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy cd cozy-oauth-proxy docker-compose up -d","title":"Proxy"},{"location":"ecolyo/project_architecture/environments/#ecolyo-and-konnectors","text":"By default the version present on the \"build-dev\" branch is used to install Ecolyo app and konnectors on a new instance. Some scripts has been created in order to install, update, downgrade, remove app and konnectors. Please refer to the dedicated section for more information.","title":"Ecolyo and konnectors"},{"location":"ecolyo/project_architecture/environments/#prod-environment","text":"This environment is fully managed by Cozy team.","title":"Prod environment"},{"location":"ecolyo/project_architecture/environments/#cozy-stack_1","text":"Fully managed by Cozy team.","title":"Cozy stack"},{"location":"ecolyo/project_architecture/environments/#proxy_1","text":"A dedicated proxy is deployed on Cozy side to allow konnector to make the OAuth dance. The proxy deployed is based on the project available on the GitLab but variables are overwritten using flags by the Cozy team in order to fit to the environment. For each modification in production, it needs: - to be done on the gitLab project - to be testeded in dev environnment After that we should ask Cozy to pull the modification from the GitLab in order to have them in production.","title":"Proxy"},{"location":"ecolyo/project_architecture/environments/#ecolyo-and-konnectors_1","text":"The production environment is based on the build branch which should reflect the build of sources present on master branch. Each deployment is done manually for each app/konnector by: - building the application (yarn build) - deploy the build on the build branch (yarn deploy) - publishing content of build branch into Cozy repository (yarn cozyPublish) Once it is published, Cozy team should validate it before deploying the new app version into all Cozy Grand Lyon instances.","title":"Ecolyo and konnectors"},{"location":"ecolyo/project_architecture/libraries/","text":"Libraries For this project, we use the libraries below: React Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM React Redux It is a predictable state container. It is implemented for a better management of the states because it allows to centralize all the states and the logic of the application. It lets a react component read data from a Redux store, and dispatch actions to the store to update data. Axios HTTP client library It allows to send HTTP request and manage the responses. Lodash javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions Moment Date library to parse, validate, manipulate, and display dates and times in JavaScript. Luxon Wrapper for Javascript dates and times. Jest Testing library It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product. Enzyme Testing utility for React It makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output. Sass CSS preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations. Material UI It allows to create react component that implements Google's material design D3 It allows to manipulate documents based on data. It combines visualization components and a data-driven approach to DOM manipulation. React-swipeable-views It is a React component to make swipeable views React-lottie Lottie Animation View for React. It allows app to use animations easily. Husky It is used to improve your commit.","title":"Libraries"},{"location":"ecolyo/project_architecture/libraries/#libraries","text":"For this project, we use the libraries below:","title":"Libraries"},{"location":"ecolyo/project_architecture/libraries/#react","text":"Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM","title":"React"},{"location":"ecolyo/project_architecture/libraries/#react-redux","text":"It is a predictable state container. It is implemented for a better management of the states because it allows to centralize all the states and the logic of the application. It lets a react component read data from a Redux store, and dispatch actions to the store to update data.","title":"React Redux"},{"location":"ecolyo/project_architecture/libraries/#axios","text":"HTTP client library It allows to send HTTP request and manage the responses.","title":"Axios"},{"location":"ecolyo/project_architecture/libraries/#lodash","text":"javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions","title":"Lodash"},{"location":"ecolyo/project_architecture/libraries/#moment","text":"Date library to parse, validate, manipulate, and display dates and times in JavaScript.","title":"Moment"},{"location":"ecolyo/project_architecture/libraries/#luxon","text":"Wrapper for Javascript dates and times.","title":"Luxon"},{"location":"ecolyo/project_architecture/libraries/#jest","text":"Testing library It allows to evaluate functionnalities of an app to ensure that the product is defect-free in order to produce the quality product.","title":"Jest"},{"location":"ecolyo/project_architecture/libraries/#enzyme","text":"Testing utility for React It makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.","title":"Enzyme"},{"location":"ecolyo/project_architecture/libraries/#sass","text":"CSS preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.","title":"Sass"},{"location":"ecolyo/project_architecture/libraries/#material-ui","text":"It allows to create react component that implements Google's material design","title":"Material UI"},{"location":"ecolyo/project_architecture/libraries/#d3","text":"It allows to manipulate documents based on data. It combines visualization components and a data-driven approach to DOM manipulation.","title":"D3"},{"location":"ecolyo/project_architecture/libraries/#react-swipeable-views","text":"It is a React component to make swipeable views","title":"React-swipeable-views"},{"location":"ecolyo/project_architecture/libraries/#react-lottie","text":"Lottie Animation View for React. It allows app to use animations easily.","title":"React-lottie"},{"location":"ecolyo/project_architecture/libraries/#husky","text":"It is used to improve your commit.","title":"Husky"},{"location":"ecolyo/project_architecture/remote_doctypes/","text":"Creation of the remote doctype The remote doctype should be created in the cozy repository : https://github.com/cozy/cozy-doctypes Remote doctype org.ecolyo.usage To create the remote the first create a folder named 'org.ecolyo.usage' and then add a file named request in the folder. Here is the structure of the file: POST https://API_URL Content-Type: application/json {{ data }} Local remote doctype As the doctype is not yet avaible on cozy repository, we first need to test it on local. For that we can use the \u2014doctypes command in the cozy-stack serve and use it to point to a local repository. Here are the step: clone the repository and add it in the ecolyo repository create the remote doctype. Here we create a new folder named 'org.ecolyo.usage' and add the following request file (replace API_URL by the url of the API): POST https://API_URL Content-Type: application/json {{ data }} add the \u2014doctypes command in the \"docker/cozy-app-dev-with-app.sh\" file and also the -remote-allow-custom-port flag ${ COZY_STACK_PATH } serve --allow-root \\ --appdir \" ${ appdir } \" \\ --host \"::\" \\ --port \" ${ COZY_STACK_PORT } \" \\ --admin-port \" ${ COZY_STACK_ADMIN_PORT } \" \\ --couchdb-url \" ${ COUCHDB_URL } \" \\ --doctypes /data/cozy-doctypes \\ --mail-port 1025 \\ --mail-disable-tls \\ --remote-allow-custom-port \\ --fs-url \"file://localhost ${ vfsdir } \" & add the following content in \"docker/disableCSP.yaml\": remote_assets : ecolyo-usage : http://cozy.tools:8080/remote/org.ecolyo.usage/ Go to the docker folder in the project root cd docker build the docker image and tag it to registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env : docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env Then add the following command to winstack script in the package.json: -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: yarn winstack Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): \"request\" : \"POST https://API_URL\\nContent-Type: application/json\\n\\n{{data}}\" , Use of remote doctype in the application Add permission in manifest.webapp \"ecolyo-usage\" : { \"type\" : \"org.ecolyo.usage\" , \"verbs\" : [ \"GET\" , \"POST\" ] } Don't forget to add the description Call the remote docType: const result = await client .getStackClient() .fetchJSON('POST', '/remote/org.ecolyo.usage', { JSON.stringify(indicator), }) Passing parameters to a remote doctype In order to pass parameters to a remote doctypes such as query paramaters or headers, you need to process the following way : You can pass header directly under the URL in the request file, such as Authorization or Content-Type headers. GET https://API_URL/?q ={ queryParam } Authorization: Bearer {{ secret_token }} Content-Type: application/json When you call the remote doctype, you can directly pass the parameters to the doctype : const result = await client .getStackClient() .fetchJSON(\"GET\", \"/remote/org.ecolyo.usage/queryParam=yourParameter\"); If you wanna know more about remote doctypes and how to store and use secret tokens, please refer to the official cozy documentation. Add secrets to a remote As above, you can pass a {{secret_token}} to your remote doctype. In local, you can directly pass it as a request param in io.cozy.doctypes/org.ecolyo.usage . Otherwise, you will have to add it in the shell script easy-cozy/db-init.sh on the server. You can add the following line to the file in order to add the secret in the database : docker-compose exec db curl -X PUT -d \"{\\\"_id\\\":\\\"org.ecolyo.dju\\\",\\\"token\\\":\\\"${API_DATAGRANDLYON_TOKEN}\\\"}\" http://127.0.0.1:5984/secrets%2Fio-cozy-remote-secrets/org.ecolyo.dju Make sure you have the right remote doctype name as _id. Then, in the .env file, just add your token variable.","title":"Remote DocTypes"},{"location":"ecolyo/project_architecture/remote_doctypes/#creation-of-the-remote-doctype","text":"The remote doctype should be created in the cozy repository : https://github.com/cozy/cozy-doctypes","title":"Creation of the remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#remote-doctype-orgecolyousage","text":"To create the remote the first create a folder named 'org.ecolyo.usage' and then add a file named request in the folder. Here is the structure of the file: POST https://API_URL Content-Type: application/json {{ data }}","title":"Remote doctype org.ecolyo.usage"},{"location":"ecolyo/project_architecture/remote_doctypes/#local-remote-doctype","text":"As the doctype is not yet avaible on cozy repository, we first need to test it on local. For that we can use the \u2014doctypes command in the cozy-stack serve and use it to point to a local repository. Here are the step: clone the repository and add it in the ecolyo repository create the remote doctype. Here we create a new folder named 'org.ecolyo.usage' and add the following request file (replace API_URL by the url of the API): POST https://API_URL Content-Type: application/json {{ data }} add the \u2014doctypes command in the \"docker/cozy-app-dev-with-app.sh\" file and also the -remote-allow-custom-port flag ${ COZY_STACK_PATH } serve --allow-root \\ --appdir \" ${ appdir } \" \\ --host \"::\" \\ --port \" ${ COZY_STACK_PORT } \" \\ --admin-port \" ${ COZY_STACK_ADMIN_PORT } \" \\ --couchdb-url \" ${ COUCHDB_URL } \" \\ --doctypes /data/cozy-doctypes \\ --mail-port 1025 \\ --mail-disable-tls \\ --remote-allow-custom-port \\ --fs-url \"file://localhost ${ vfsdir } \" & add the following content in \"docker/disableCSP.yaml\": remote_assets : ecolyo-usage : http://cozy.tools:8080/remote/org.ecolyo.usage/ Go to the docker folder in the project root cd docker build the docker image and tag it to registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env : docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env Then add the following command to winstack script in the package.json: -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: yarn winstack Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): \"request\" : \"POST https://API_URL\\nContent-Type: application/json\\n\\n{{data}}\" ,","title":"Local remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#use-of-remote-doctype-in-the-application","text":"Add permission in manifest.webapp \"ecolyo-usage\" : { \"type\" : \"org.ecolyo.usage\" , \"verbs\" : [ \"GET\" , \"POST\" ] } Don't forget to add the description Call the remote docType: const result = await client .getStackClient() .fetchJSON('POST', '/remote/org.ecolyo.usage', { JSON.stringify(indicator), })","title":"Use of remote doctype in the application"},{"location":"ecolyo/project_architecture/remote_doctypes/#passing-parameters-to-a-remote-doctype","text":"In order to pass parameters to a remote doctypes such as query paramaters or headers, you need to process the following way : You can pass header directly under the URL in the request file, such as Authorization or Content-Type headers. GET https://API_URL/?q ={ queryParam } Authorization: Bearer {{ secret_token }} Content-Type: application/json When you call the remote doctype, you can directly pass the parameters to the doctype : const result = await client .getStackClient() .fetchJSON(\"GET\", \"/remote/org.ecolyo.usage/queryParam=yourParameter\"); If you wanna know more about remote doctypes and how to store and use secret tokens, please refer to the official cozy documentation.","title":"Passing parameters to a remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#add-secrets-to-a-remote","text":"As above, you can pass a {{secret_token}} to your remote doctype. In local, you can directly pass it as a request param in io.cozy.doctypes/org.ecolyo.usage . Otherwise, you will have to add it in the shell script easy-cozy/db-init.sh on the server. You can add the following line to the file in order to add the secret in the database : docker-compose exec db curl -X PUT -d \"{\\\"_id\\\":\\\"org.ecolyo.dju\\\",\\\"token\\\":\\\"${API_DATAGRANDLYON_TOKEN}\\\"}\" http://127.0.0.1:5984/secrets%2Fio-cozy-remote-secrets/org.ecolyo.dju Make sure you have the right remote doctype name as _id. Then, in the .env file, just add your token variable.","title":"Add secrets to a remote"},{"location":"ecolyo/services/","text":"In order to build an automated task within our cozy-stack, we can create services which are javascript files called from a trigger job. For instance on Ecolyo, to schedule a mail that alert the user that a new monthly report is available in the application, we add a trigger that is launched every month with a cron attribute. On that trigger we link a .js script then we instanciate this script with cozy-client. Configuration Manifest The service should be described in the manifest.webapp file. it should defined the type, the file and the trigger. See more information in the official doc of Cozy here Here is an example of service declaration in the ecolyo manifest: File location is determined after the build, see here . Cron See the cron definition at cozy-stack . Ecolyo services Service code are located under src\\targets\\services .","title":"Description"},{"location":"ecolyo/services/#configuration","text":"","title":"Configuration"},{"location":"ecolyo/services/#manifest","text":"The service should be described in the manifest.webapp file. it should defined the type, the file and the trigger. See more information in the official doc of Cozy here Here is an example of service declaration in the ecolyo manifest: File location is determined after the build, see here . Cron See the cron definition at cozy-stack .","title":"Manifest"},{"location":"ecolyo/services/#ecolyo-services","text":"Service code are located under src\\targets\\services .","title":"Ecolyo services"},{"location":"ecolyo/services/aggregator_usage_events/","text":"Definition of the service The service will run each day at [TO BE DEFINED], as defined in the manifest: \"aggregatorUsageEvents\": { \"type\": \"node\", \"file\": \"services/aggregatorUsageEvents/ecolyo.js\", \"trigger\": \"[TO BE DEFINED]\" } Main responsabilities of the service The service is responsible of : Collecting all new events from the com.grandlyon.ecolyo.usageevents Aggregated them to indicators Send indicators to the remote doctype To do As the remote doctype is not yet available for the service here are the remaining task to do: In the manifest.webapp: Declare the remote doctype (see here)[/ecolyo/project_architecture/remote_doctypes.md] Define the cron to run every day: to check with cozy to ensure that all instances will not trigger the service at the same time Create the translation for \"fr\" and \"en\" In the service: Update the remote doctype name in the sendIndicator method Add a check on the environment to ensure that the service will not post information on the remote doctype when its comes for alpha instance","title":"Aggregator usage events"},{"location":"ecolyo/services/aggregator_usage_events/#definition-of-the-service","text":"The service will run each day at [TO BE DEFINED], as defined in the manifest: \"aggregatorUsageEvents\": { \"type\": \"node\", \"file\": \"services/aggregatorUsageEvents/ecolyo.js\", \"trigger\": \"[TO BE DEFINED]\" }","title":"Definition of the service"},{"location":"ecolyo/services/aggregator_usage_events/#main-responsabilities-of-the-service","text":"The service is responsible of : Collecting all new events from the com.grandlyon.ecolyo.usageevents Aggregated them to indicators Send indicators to the remote doctype","title":"Main responsabilities of the service"},{"location":"ecolyo/services/aggregator_usage_events/#to-do","text":"As the remote doctype is not yet available for the service here are the remaining task to do: In the manifest.webapp: Declare the remote doctype (see here)[/ecolyo/project_architecture/remote_doctypes.md] Define the cron to run every day: to check with cozy to ensure that all instances will not trigger the service at the same time Create the translation for \"fr\" and \"en\" In the service: Update the remote doctype name in the sendIndicator method Add a check on the environment to ensure that the service will not post information on the remote doctype when its comes for alpha instance","title":"To do"},{"location":"ecolyo/services/consumption_alert/","text":"Definition of the service The service will run everyday at 10.00 am, as defined in the manifest: \"consumptionAlert\": { \"type\": \"node\", \"file\": \"services/consumptionAlert/ecolyo.js\", \"trigger\": \"@cron 0 3 * * *\" } Main responsabilities of the service The service is reponsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel). For now it only monitors water consumptions. Main steps are the following: - Check the \"sendConsumptionAlert\" and \"waterDailyConsumptionLimit\" attributes in the com.grandlyon.ecolyo.profile doctype. If \"sendConsumptionAlert\" is set to true and \"waterDailyConsumptionLimit\" is not set to 0, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url, consumption of the last day fetched by the egl konnector). - Check that the last consumption is greater than the limit set by the user. If false the service will stop. - Build the mail. - Send the mail. Sending mail Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Consumption Alert"},{"location":"ecolyo/services/consumption_alert/#definition-of-the-service","text":"The service will run everyday at 10.00 am, as defined in the manifest: \"consumptionAlert\": { \"type\": \"node\", \"file\": \"services/consumptionAlert/ecolyo.js\", \"trigger\": \"@cron 0 3 * * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/consumption_alert/#main-responsabilities-of-the-service","text":"The service is reponsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel). For now it only monitors water consumptions. Main steps are the following: - Check the \"sendConsumptionAlert\" and \"waterDailyConsumptionLimit\" attributes in the com.grandlyon.ecolyo.profile doctype. If \"sendConsumptionAlert\" is set to true and \"waterDailyConsumptionLimit\" is not set to 0, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url, consumption of the last day fetched by the egl konnector). - Check that the last consumption is greater than the limit set by the user. If false the service will stop. - Build the mail. - Send the mail.","title":"Main responsabilities of the service"},{"location":"ecolyo/services/consumption_alert/#sending-mail","text":"Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Sending mail"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/","text":"Definition of the service The service will run everyday 3rd of month at 8.00 am, as defined in the manifest: \"enedisHalfHourMonthlyAnalysis\": { \"type\": \"node\", \"file\": \"services/enedisHalfHourMonthlyAnalysis/ecolyo.js\", \"trigger\": \"@cron 0 0 8 3 * *\" } Main responsabilities of the service The service is reponsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype com.grandlyon.enedis.monthly.analysis.data Main steps are the following : Check com.grandlyon.enedis.minute doctype. If the doctype contains entries, it means the half-hour consumption tracking has been activated, and there is data to use. If there is half-hour data, creates the average consumption load for the last month (for the analysis) and store it in the doctype com.grandlyon.enedis.monthly.analysis.data Checks if there is other entries in this doctype, if so, it means the service has already run before, so we create and store enedis monthly analysis for every month between the first entry in the enedis.minute doctype and the first entry in the enedis.monthly.analysis doctype. This way we will have an analysis available until the first month the half-hour consumption tracking has been activated If there is no other entries in this doctype, it means it is the first the service runs, so we create and store enedis analysis from the last month analysis and until the minimum date between 1 year ago and the the date of first enedis.minute doctype entry. Calculating the average half-hour consumption In order to calculate the average half-hour consumption on a given month, we use the function getEnedisMonthAnalysisData which takes the cozy client , a month and a year in parameters. This function is charged to do the following things : Get the graph data for the chosen month on the given month period. For each day, get the half-hour consumption Filter days in 2 parts : weekdays and week end days For each half-hour data push the data in a global 2dimensionnal array ; there is 2 global array, one for week-end days and the other for weekdays At the point we have 2 global array with each 48 arrays filled with the corresponding values. To illustrate this, here is an example of how the data is sorted : weekEndValuesArray : [ 8h-8h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 8h30-9h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 9h-9h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ... 23h30-00h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ] - Once the array is filled with all available values, we just have to calculate the average for each half-hour step The minimum value is calculated by the getMonthMinLoad function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplicated with 48 (the number of half hour entries in a day) and with the number of days in the month. The maxPower value is fetched from the doctype com.grandlyon.enedis.maxpower , the value is stored on a daily basis, so take the maximum value for the given month. The result is stored in com.grandlyon.enedis.monthly.analysis.data according to the following model : EnedisMonthlyAnalysisData { weekDaysHalfHourAverageValues: number[] weekEndDaysHalfHourAverageValues: number[] minimumLoad: number maxPower: number month: number year: number } Important rules The empty half-hour values represented by a \"-1\" are not pushed in the valuesArray so we can keep an accurate average We have no choice but to get the half-hour values day per day because cozy limits the request result number to 1000 entries, and it is not enough to get a maximum of 48*31= 1488 entries per month, plus it doesn't allows us to properly calculate and average and handle the empty values. This service is quite long to run so we decided to run it 2 hours before the newsletter sending, this way user can acces his last enedis analysis once he received the newsletter.","title":"Enedis Halfhour Monthly Analysis"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#definition-of-the-service","text":"The service will run everyday 3rd of month at 8.00 am, as defined in the manifest: \"enedisHalfHourMonthlyAnalysis\": { \"type\": \"node\", \"file\": \"services/enedisHalfHourMonthlyAnalysis/ecolyo.js\", \"trigger\": \"@cron 0 0 8 3 * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#main-responsabilities-of-the-service","text":"The service is reponsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype com.grandlyon.enedis.monthly.analysis.data Main steps are the following : Check com.grandlyon.enedis.minute doctype. If the doctype contains entries, it means the half-hour consumption tracking has been activated, and there is data to use. If there is half-hour data, creates the average consumption load for the last month (for the analysis) and store it in the doctype com.grandlyon.enedis.monthly.analysis.data Checks if there is other entries in this doctype, if so, it means the service has already run before, so we create and store enedis monthly analysis for every month between the first entry in the enedis.minute doctype and the first entry in the enedis.monthly.analysis doctype. This way we will have an analysis available until the first month the half-hour consumption tracking has been activated If there is no other entries in this doctype, it means it is the first the service runs, so we create and store enedis analysis from the last month analysis and until the minimum date between 1 year ago and the the date of first enedis.minute doctype entry.","title":"Main responsabilities of the service"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#calculating-the-average-half-hour-consumption","text":"In order to calculate the average half-hour consumption on a given month, we use the function getEnedisMonthAnalysisData which takes the cozy client , a month and a year in parameters. This function is charged to do the following things : Get the graph data for the chosen month on the given month period. For each day, get the half-hour consumption Filter days in 2 parts : weekdays and week end days For each half-hour data push the data in a global 2dimensionnal array ; there is 2 global array, one for week-end days and the other for weekdays At the point we have 2 global array with each 48 arrays filled with the corresponding values. To illustrate this, here is an example of how the data is sorted : weekEndValuesArray : [ 8h-8h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 8h30-9h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 9h-9h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ... 23h30-00h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ] - Once the array is filled with all available values, we just have to calculate the average for each half-hour step The minimum value is calculated by the getMonthMinLoad function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplicated with 48 (the number of half hour entries in a day) and with the number of days in the month. The maxPower value is fetched from the doctype com.grandlyon.enedis.maxpower , the value is stored on a daily basis, so take the maximum value for the given month. The result is stored in com.grandlyon.enedis.monthly.analysis.data according to the following model : EnedisMonthlyAnalysisData { weekDaysHalfHourAverageValues: number[] weekEndDaysHalfHourAverageValues: number[] minimumLoad: number maxPower: number month: number year: number }","title":"Calculating the average half-hour consumption"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#important-rules","text":"The empty half-hour values represented by a \"-1\" are not pushed in the valuesArray so we can keep an accurate average We have no choice but to get the half-hour values day per day because cozy limits the request result number to 1000 entries, and it is not enough to get a maximum of 48*31= 1488 entries per month, plus it doesn't allows us to properly calculate and average and handle the empty values. This service is quite long to run so we decided to run it 2 hours before the newsletter sending, this way user can acces his last enedis analysis once he received the newsletter.","title":"Important rules"},{"location":"ecolyo/services/monthly_report_notification/","text":"Definition of the service The service will run the 3rd of each month at 10.00 am, as defined in the manifest: \"monthlyReportNotification\": { \"type\": \"node\", \"file\": \"services/monthlyReportNotification/ecolyo.js\", \"trigger\": \"@cron 0 0 10 3 * *\" } Main responsabilities of the service The service is reponsible of sending a mail to user to warn him about the availability of a new information in the Analyse. Main steps are the following: - Check the \"sendReportNotification\" attribute in the com.grandlyon.ecolyo.profile doctype. If true, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url). - Build the mail. - Send the mail. Sending mail Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Monthly report notification"},{"location":"ecolyo/services/monthly_report_notification/#definition-of-the-service","text":"The service will run the 3rd of each month at 10.00 am, as defined in the manifest: \"monthlyReportNotification\": { \"type\": \"node\", \"file\": \"services/monthlyReportNotification/ecolyo.js\", \"trigger\": \"@cron 0 0 10 3 * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/monthly_report_notification/#main-responsabilities-of-the-service","text":"The service is reponsible of sending a mail to user to warn him about the availability of a new information in the Analyse. Main steps are the following: - Check the \"sendReportNotification\" attribute in the com.grandlyon.ecolyo.profile doctype. If true, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url). - Build the mail. - Send the mail.","title":"Main responsabilities of the service"},{"location":"ecolyo/services/monthly_report_notification/#sending-mail","text":"Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Sending mail"},{"location":"konnectors/","text":"Konnectors are scripts that import data from a web service and put those data into cozy. Each konnector is an independant application managed by the cozy home application. Ecolyo uses data from 3 web services : Enedis Grdf Eau du grand lyon (EGL) All the konnectors are configured to retrieve user's data as far as 3 years back. Some variation have to be considered : When the user launches the konnector manually, it fetches 1 year of data (in order to reduce running time). When a konnector is launched by the cozy stack (at a random time between 10am and 11am), it fetches 3 years of data. When a konnector retrieves a load at the half-hour timeline (ex: enedis), it fetches back to 4 weeks.","title":"Introduction"},{"location":"konnectors/egl/","text":"EGL Konnector This konnector fetches consumptions measures from EGL API. The EGL API allows us to get a user's consumption data gathered by it's connected water meter \"T\u00e9l\u00e9o\". You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ API Url for Development : https://agence-rec.eaudugrandlyon.com API Url for Production : https://agence.eaudugrandlyon.com/ws Authentication In order to authenticate to the EGL API we have to request the following route Method : POST Authentication Route : /connect.asp \"headers\" : { { \"AuthKey\" : <your - au t h - key> , \"Content-Type\" : \"application/x-www-form-urlencoded\" } } \"body\" : { \"mode\" : \"formdata\" { \"login\" : <your - logi n > , \"pass\" : <your - password> } } Once you've sent this request the API should answer with a code 100 if everything is ok and provides you a valid token and num_abt that you will use later in order to get data. { \"codeRetour\" : 100 , \"libelleRetour\" : \"Connect\u00e9\" , \"resultatRetour\" : { \"num_abt\" : t o t o , \"list_num_abt\" : [ t o t o , tata ] \"token\" : \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\" } } Fetch Data In order to get data from the EGL API we have to request the following route : Method : POST Data Route : /getAllAgregatsByAbonnement.aspx \"body\" : { \"mode\" : \"formdata\" { \"token\" : \"897555754A703055397897456568776E32704C3953514F5R\" , \"num_abt\" : 1895683 , \"date_debut\" : MM/JJ/YYYY , \"date_fin\" : MM/JJ/YYYY } } The dates must be valid dates otherwise you'll get an error The answer will provide you an array of data day by day with the value got by the water meter 'ValeurIndex' at this moment. { \"codeRetour\" : 100 , \"libelleRetour\" : \"L'op\u00e9ration a r\u00e9ussi\" , \"resultatRetour\" : [ { \"DateReleve\" : \"2020-07-01T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562362 }, { \"DateReleve\" : \"2020-07-02T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562432 } ] } Daily data is calculated by substracting current valeurIndex day with previous day. TypeAgregats \"R\" means the real value \"A\" means an anomaly \"D\" means a water meter changing \"V\" means data has been estimated on a period \"X\" marks the start and end of \"V\" estimated data \"T\" means pending data If you're looking for more information about the API, checkout the complete API documentation Konnector Methods Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data authenticate Authentication method. Requires login, password, baseUrl and ApiAuthKey. storeData Save data in the right doctype db and prevent duplicated keys format Format data for DB storage and remove bad data (former \"T\" typeagregats remain in response even if the data was added later, leading to duplicated data) resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.egl.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after egl data reprocess","title":"Eau du Grand Lyon"},{"location":"konnectors/egl/#egl-konnector","text":"This konnector fetches consumptions measures from EGL API. The EGL API allows us to get a user's consumption data gathered by it's connected water meter \"T\u00e9l\u00e9o\". You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ API Url for Development : https://agence-rec.eaudugrandlyon.com API Url for Production : https://agence.eaudugrandlyon.com/ws","title":"EGL Konnector"},{"location":"konnectors/egl/#authentication","text":"In order to authenticate to the EGL API we have to request the following route Method : POST Authentication Route : /connect.asp \"headers\" : { { \"AuthKey\" : <your - au t h - key> , \"Content-Type\" : \"application/x-www-form-urlencoded\" } } \"body\" : { \"mode\" : \"formdata\" { \"login\" : <your - logi n > , \"pass\" : <your - password> } } Once you've sent this request the API should answer with a code 100 if everything is ok and provides you a valid token and num_abt that you will use later in order to get data. { \"codeRetour\" : 100 , \"libelleRetour\" : \"Connect\u00e9\" , \"resultatRetour\" : { \"num_abt\" : t o t o , \"list_num_abt\" : [ t o t o , tata ] \"token\" : \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\" } }","title":"Authentication"},{"location":"konnectors/egl/#fetch-data","text":"In order to get data from the EGL API we have to request the following route : Method : POST Data Route : /getAllAgregatsByAbonnement.aspx \"body\" : { \"mode\" : \"formdata\" { \"token\" : \"897555754A703055397897456568776E32704C3953514F5R\" , \"num_abt\" : 1895683 , \"date_debut\" : MM/JJ/YYYY , \"date_fin\" : MM/JJ/YYYY } } The dates must be valid dates otherwise you'll get an error The answer will provide you an array of data day by day with the value got by the water meter 'ValeurIndex' at this moment. { \"codeRetour\" : 100 , \"libelleRetour\" : \"L'op\u00e9ration a r\u00e9ussi\" , \"resultatRetour\" : [ { \"DateReleve\" : \"2020-07-01T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562362 }, { \"DateReleve\" : \"2020-07-02T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562432 } ] } Daily data is calculated by substracting current valeurIndex day with previous day.","title":"Fetch Data"},{"location":"konnectors/egl/#typeagregats","text":"\"R\" means the real value \"A\" means an anomaly \"D\" means a water meter changing \"V\" means data has been estimated on a period \"X\" marks the start and end of \"V\" estimated data \"T\" means pending data If you're looking for more information about the API, checkout the complete API documentation","title":"TypeAgregats"},{"location":"konnectors/egl/#konnector-methods","text":"Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data authenticate Authentication method. Requires login, password, baseUrl and ApiAuthKey. storeData Save data in the right doctype db and prevent duplicated keys format Format data for DB storage and remove bad data (former \"T\" typeagregats remain in response even if the data was added later, leading to duplicated data) resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.egl.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after egl data reprocess","title":"Konnector Methods"},{"location":"konnectors/enedis/","text":"This konnector fetches consumptions measures from Enedis API. This is an Oauth Konnector, meaning the authentification performed to access all data is made following an Oauth2 protocol. You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ https://docs.cozy.io/en/tutorials/konnector/oauth/ Enedis Konnector The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentification. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the usage_point_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, if no usage_point_id are found in database or fields then proceed as a first launch. Store the usage_point_id in oauth_callback_result in db (see addData ). Konnector finds usage point_id when starting but token is expired. Proceed to refresh token and restart konnector with usage_point_id in fields params (see _Troubleshooting when asking for refresh token section at the end of the page). Enedis API API Url for Production : https://gw.prd.api.enedis.fr API url for Development : https://gw.hml.api.enedis.fr Once you've finished the OAuth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo: Method : GET Route : /v4/metering_data/consumption_load_curve Method : GET Route : /v4/metering_data/daily_consumption Method : GET Route : /v4/metering_data/daily_consumption_max_power \"params\" : { \"usage_point_id\" : <your - usage - poi nt - id> , \"start\" : \"YYYY-MM-DD\" , \"end\" : \"YYYY-MM-DD\" , } \"headers\" : { \"Accept\" : \"application/json\" , \"Authorization\" : \"Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } For more information about Datahub-Enedis API, checkout the Datahub documentation . Konnector Methods Method Description start Init Function getDailyData Retrieve data from the API. Format: { value: \"Wh\", \"date\": \"YYYY-MM-DD\" } \" startLoadDataProcess Check if history is loaded. If not, call several time the api to retrieve 1 month of history for load data. If yes only call once the api launchLoadDataProcess Launch process to handle load data getLoadData Retrieve data from the API. Format: { value: \"W\", \"date\": \"YYYY-MM-DD hh:mm:ss\" } processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data agregateMonthAndYearData Agregate data from daily data to monthly and yearly data agregateHourlyData Agregate data from load data (every 30 min) to Hourly data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAgregatedData Retrieve and remove old data for a specific doctype and return an array of agregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" getMaxPower Retrieve data from the maxPower API. Format: { value: \"kVA\", \"date\": \"YYYY-MM-DD\" } isHistoryLoaded Function checking if the history is loaded resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.enedis.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after enedis data reprocess Troubleshooting when asking for refresh token When a token expires, the konnector will encounter an error when fetching user data, leading to a refresh token request. Since refresh token requests restart the Konnector, it was decided to add the usage_point_id into the start fields when asking for a refresh token (see line 97). restart to refresh token Line 85: await cozyClient.fetchJSON( 'POST', `/accounts/enedisgrandlyon/${accountId}/refresh` ) Line 97: ```fields.usage_point_id = usage_point_id``` Line 98: ```return start(fields, cozyParameters, false)``` In fact the usage_point_id still remains in the account collection, but on restart, the konnector loses this._account context leading to an error when searching for usage_point_id in account. Half-hour data issue When requesting the load curve api while the half-hour data is not activated, we may have an error response 404 with a message \"no data found\", which makes the whole data fetching process crash. So instead of making it crash we just log this particular error and avoid the konnector to crash. So we added a condition in line 227, in the checkConsentForLoadCurve function : if ( (err.statusCode === 404 || err.code === 404) && err.message.search('no_data_found') > 0 ) { log('info', 'Handling half-hour error on connection') return false }","title":"Enedis"},{"location":"konnectors/enedis/#enedis-konnector","text":"The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentification. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the usage_point_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, if no usage_point_id are found in database or fields then proceed as a first launch. Store the usage_point_id in oauth_callback_result in db (see addData ). Konnector finds usage point_id when starting but token is expired. Proceed to refresh token and restart konnector with usage_point_id in fields params (see _Troubleshooting when asking for refresh token section at the end of the page).","title":"Enedis Konnector"},{"location":"konnectors/enedis/#enedis-api","text":"API Url for Production : https://gw.prd.api.enedis.fr API url for Development : https://gw.hml.api.enedis.fr Once you've finished the OAuth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo: Method : GET Route : /v4/metering_data/consumption_load_curve Method : GET Route : /v4/metering_data/daily_consumption Method : GET Route : /v4/metering_data/daily_consumption_max_power \"params\" : { \"usage_point_id\" : <your - usage - poi nt - id> , \"start\" : \"YYYY-MM-DD\" , \"end\" : \"YYYY-MM-DD\" , } \"headers\" : { \"Accept\" : \"application/json\" , \"Authorization\" : \"Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } For more information about Datahub-Enedis API, checkout the Datahub documentation .","title":"Enedis API"},{"location":"konnectors/enedis/#konnector-methods","text":"Method Description start Init Function getDailyData Retrieve data from the API. Format: { value: \"Wh\", \"date\": \"YYYY-MM-DD\" } \" startLoadDataProcess Check if history is loaded. If not, call several time the api to retrieve 1 month of history for load data. If yes only call once the api launchLoadDataProcess Launch process to handle load data getLoadData Retrieve data from the API. Format: { value: \"W\", \"date\": \"YYYY-MM-DD hh:mm:ss\" } processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data agregateMonthAndYearData Agregate data from daily data to monthly and yearly data agregateHourlyData Agregate data from load data (every 30 min) to Hourly data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAgregatedData Retrieve and remove old data for a specific doctype and return an array of agregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" getMaxPower Retrieve data from the maxPower API. Format: { value: \"kVA\", \"date\": \"YYYY-MM-DD\" } isHistoryLoaded Function checking if the history is loaded resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.enedis.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after enedis data reprocess","title":"Konnector Methods"},{"location":"konnectors/enedis/#troubleshooting-when-asking-for-refresh-token","text":"When a token expires, the konnector will encounter an error when fetching user data, leading to a refresh token request. Since refresh token requests restart the Konnector, it was decided to add the usage_point_id into the start fields when asking for a refresh token (see line 97). restart to refresh token Line 85: await cozyClient.fetchJSON( 'POST', `/accounts/enedisgrandlyon/${accountId}/refresh` ) Line 97: ```fields.usage_point_id = usage_point_id``` Line 98: ```return start(fields, cozyParameters, false)``` In fact the usage_point_id still remains in the account collection, but on restart, the konnector loses this._account context leading to an error when searching for usage_point_id in account.","title":"Troubleshooting when asking for refresh token"},{"location":"konnectors/enedis/#half-hour-data-issue","text":"When requesting the load curve api while the half-hour data is not activated, we may have an error response 404 with a message \"no data found\", which makes the whole data fetching process crash. So instead of making it crash we just log this particular error and avoid the konnector to crash. So we added a condition in line 227, in the checkConsentForLoadCurve function : if ( (err.statusCode === 404 || err.code === 404) && err.message.search('no_data_found') > 0 ) { log('info', 'Handling half-hour error on connection') return false }","title":"Half-hour data issue"},{"location":"konnectors/grdf/","text":"This konnector fetches consumptions measures from Grdf Adict API. This is an Oauth Konnector, meaning the authentification performed to access all data is made following an Oauth2 protocol. You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ https://docs.cozy.io/en/tutorials/konnector/oauth/ Grdf Adict Konnector The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentification. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the pce_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, fails to find a pce_id in database on first launch therefore decodes the id_token to store the pce_id in db (see addData ). Konnector restarts, this time knowing a pce_id, it fails to fetch datas because the access_token from oauth call has a reduced scope (only scoping for meta data requests). Konnector launches a refresh call, the proxy knows to answer it with a client_credentials grant_type call to grdf /access_token. Konnector restarts with everyting needed in database to fetch datas and store them in couchdb. Further jobs will not need to change scope again and will only ask for refresh tokens. Konnector Flow summarized On delete account When deleting one's konnector account, src/onDeleteAccount.js is triggered. In order to facilitate a new oauth connection later on. It aims to remove user's consent between its grdf account and the Metropole de Lyon. To do so, we use the secret credentials stored in account_type grdfgrandlyon.delete (see cozy offical documentation to know how we create a special account_type secret) to generate an access_token with enough permission to revoke any consents given to the Metropole. Launch on standalone In the project repository type yarn standalone to launch the konnector without a cozy stack running. Installation Build the konnector with yarn build . Install on easy-cozy (development purposes) sudo docker cp /home/easy-cozy/fun/grdf-konnector/build/ $container_id:/tmp/grdf-oauth sudo docker-compose exec cozy ./cozy konnectors install grdf-oauth --domain \"$alphaDomain\" file:///tmp/grdf-oauth $container_id Install on production Type yarn deploy to build on a dedicated branch. Build branch is stored as a docker image in a registry : Container Registry . Konnector Methods Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAgregatedData Retrieve and remove old data for a specific doctype and return an array of agregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.grdf.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after grdf data reprocess","title":"GRDF"},{"location":"konnectors/grdf/#grdf-adict-konnector","text":"The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentification. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the pce_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, fails to find a pce_id in database on first launch therefore decodes the id_token to store the pce_id in db (see addData ). Konnector restarts, this time knowing a pce_id, it fails to fetch datas because the access_token from oauth call has a reduced scope (only scoping for meta data requests). Konnector launches a refresh call, the proxy knows to answer it with a client_credentials grant_type call to grdf /access_token. Konnector restarts with everyting needed in database to fetch datas and store them in couchdb. Further jobs will not need to change scope again and will only ask for refresh tokens.","title":"Grdf Adict Konnector"},{"location":"konnectors/grdf/#konnector-flow-summarized","text":"","title":"Konnector Flow summarized"},{"location":"konnectors/grdf/#on-delete-account","text":"When deleting one's konnector account, src/onDeleteAccount.js is triggered. In order to facilitate a new oauth connection later on. It aims to remove user's consent between its grdf account and the Metropole de Lyon. To do so, we use the secret credentials stored in account_type grdfgrandlyon.delete (see cozy offical documentation to know how we create a special account_type secret) to generate an access_token with enough permission to revoke any consents given to the Metropole.","title":"On delete account"},{"location":"konnectors/grdf/#launch-on-standalone","text":"In the project repository type yarn standalone to launch the konnector without a cozy stack running.","title":"Launch on standalone"},{"location":"konnectors/grdf/#installation","text":"Build the konnector with yarn build .","title":"Installation"},{"location":"konnectors/grdf/#install-on-easy-cozy-development-purposes","text":"sudo docker cp /home/easy-cozy/fun/grdf-konnector/build/ $container_id:/tmp/grdf-oauth sudo docker-compose exec cozy ./cozy konnectors install grdf-oauth --domain \"$alphaDomain\" file:///tmp/grdf-oauth $container_id","title":"Install on easy-cozy (development purposes)"},{"location":"konnectors/grdf/#install-on-production","text":"Type yarn deploy to build on a dedicated branch. Build branch is stored as a docker image in a registry : Container Registry .","title":"Install on production"},{"location":"konnectors/grdf/#konnector-methods","text":"Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAgregatedData Retrieve and remove old data for a specific doctype and return an array of agregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.grdf.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after grdf data reprocess","title":"Konnector Methods"},{"location":"pilote/","text":"Pilote aims to help people in various administrative processes, allowing them to share their personnal informations with a social worker to build the best possible claim for every needs. Reminder If you're a new developer tasked to work on this project, please get acquainted with the team processes and read the advised dev environment documentation and the self-data prerequisites . Repositories global backend travailleur social front usager Acces to the application deployed DEV : https://pilote-agent-dev.grandlyon.com/ REC : https://pilote-agent-rec.grandlyon.com/ PROD : https://pilote-agent.grandlyon.com/","title":"Introduction"},{"location":"pilote/#repositories","text":"global backend travailleur social front usager","title":"Repositories"},{"location":"pilote/#acces-to-the-application-deployed","text":"DEV : https://pilote-agent-dev.grandlyon.com/ REC : https://pilote-agent-rec.grandlyon.com/ PROD : https://pilote-agent.grandlyon.com/","title":"Acces to the application deployed"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/application/deploy/","text":"Deployment For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline linked is running. On master branch, only build is set on the pipeline.","title":"Deploy"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/application/deploy/#deployment","text":"For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline linked is running. On master branch, only build is set on the pipeline.","title":"Deployment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/","text":"This section explains the different API route. Descriptions are not currently up-to-date. A swagger documentation can be consulted at http://localhost:3000/api/doc/ Auth api/auth/signin : It is used for local and dev authentification. It is linked to two different password into the database. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/token/check : It is used for check one token. It is called from cozy-stack service of the usager. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/login : It is used for Sign&Go authentification. Linked to AuthStrategy. login/callback : Get the authentification from Sign&Go process. Beneficiary /api/beneficiaire : Get all usager known from Postgre database. /api/beneficiaire/create' : This rotue is used in order to store Usager domain and his trigger proccess from Cozy. This route is protected by a COZY_SECRET env variable token. This token is generated by us. If you change it, you need to inform Cozy team because this token is store in their side also. /api/beneficiaire/remove' : This rotue is used in order to remove Usager domain and his trigger proccess. Only availabe by POST. This route is not accessible from any part of TS FRONT application. Protected rout by the same token of create route. Add one benificiary by Postman Create a POST request Entry the URL: http://localhost:3020/api/beneficiaire/create or https://pilote-agent-rec.grandlyon.com/api/beneficiaire/create Push in Authorizathion/ Bearer Token => the token use by \"process.env.COZY_SECRET\" In Body, as JSON format example : {\"cozy_name\":\"pilote-rec.cozy.self-data.alpha.grandlyon.com\",\"trigger\":\"https://pilote-rec.cozy.self-data.alpha.grandlyon.com/jobs/webhooks/d010bf3fa2aed6f3c6584ea93a54affc\"} Local : {\"cozy_name\":\"pilote.cozy.tools:8080\",\"trigger\":\"http://pilote.cozy.tools:8080/jobs/webhooks/\"} Cozy api/redirect/cozy : Allow to send information to the cozy-stack in order to run smsProccess on cozy-stask side. Users Authentification only used for local or dev environment because Sign&Go is only available for rec and prod env.","title":"Routes"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#auth","text":"api/auth/signin : It is used for local and dev authentification. It is linked to two different password into the database. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/token/check : It is used for check one token. It is called from cozy-stack service of the usager. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/login : It is used for Sign&Go authentification. Linked to AuthStrategy. login/callback : Get the authentification from Sign&Go process.","title":"Auth"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#beneficiary","text":"/api/beneficiaire : Get all usager known from Postgre database. /api/beneficiaire/create' : This rotue is used in order to store Usager domain and his trigger proccess from Cozy. This route is protected by a COZY_SECRET env variable token. This token is generated by us. If you change it, you need to inform Cozy team because this token is store in their side also. /api/beneficiaire/remove' : This rotue is used in order to remove Usager domain and his trigger proccess. Only availabe by POST. This route is not accessible from any part of TS FRONT application. Protected rout by the same token of create route.","title":"Beneficiary"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#add-one-benificiary-by-postman","text":"Create a POST request Entry the URL: http://localhost:3020/api/beneficiaire/create or https://pilote-agent-rec.grandlyon.com/api/beneficiaire/create Push in Authorizathion/ Bearer Token => the token use by \"process.env.COZY_SECRET\" In Body, as JSON format example : {\"cozy_name\":\"pilote-rec.cozy.self-data.alpha.grandlyon.com\",\"trigger\":\"https://pilote-rec.cozy.self-data.alpha.grandlyon.com/jobs/webhooks/d010bf3fa2aed6f3c6584ea93a54affc\"} Local : {\"cozy_name\":\"pilote.cozy.tools:8080\",\"trigger\":\"http://pilote.cozy.tools:8080/jobs/webhooks/\"}","title":"Add one benificiary by Postman"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#cozy","text":"api/redirect/cozy : Allow to send information to the cozy-stack in order to run smsProccess on cozy-stask side.","title":"Cozy"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#users","text":"Authentification only used for local or dev environment because Sign&Go is only available for rec and prod env.","title":"Users"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial-back.git Installation of the project Start Pilote application To start Pilote application just launch the command in a PowerShell or Windows Powershell tool: yarn docker:dev If the application starts successfully you should obtain two containers running: mps-travailleursocial-back_mps_1 mps-travailleursocial-back_postgres_1 You can access by: http://localhost:3020/api It will be redirect to the Swagger UI. It allow to test the different API defined. Run Jest test To start test defined just run the command in a PowerShell or Windows Powershell tool: yarn test:watch Don't forget to uncomment ending row into beneficiary.service.ts file before to run the above command. Usefull docker command build : docker build -t mps . run container : docker-compose -f docker-compose.yml up --remove-orphans acceder \u00e0 la db du container: docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres delete image/containers: docker system prune -a -f voir le contenu du container: docker exec -it <id_container> bash remove container: docker container rm -f <id_container> Synapps environment check mps container : docker ps --filter \"name=mps\" or use this alias created : dpm docker stop run a service from the docker-compose file: docker-compose up -d <name_of_service> | example: docker-compose up -d mps-prod , docker-compose up -d app , ....","title":"Launch the application on local"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial-back.git","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#start-pilote-application","text":"To start Pilote application just launch the command in a PowerShell or Windows Powershell tool: yarn docker:dev If the application starts successfully you should obtain two containers running: mps-travailleursocial-back_mps_1 mps-travailleursocial-back_postgres_1 You can access by: http://localhost:3020/api It will be redirect to the Swagger UI. It allow to test the different API defined.","title":"Start Pilote application"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#run-jest-test","text":"To start test defined just run the command in a PowerShell or Windows Powershell tool: yarn test:watch Don't forget to uncomment ending row into beneficiary.service.ts file before to run the above command.","title":"Run Jest test"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#usefull-docker-command","text":"build : docker build -t mps . run container : docker-compose -f docker-compose.yml up --remove-orphans acceder \u00e0 la db du container: docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres delete image/containers: docker system prune -a -f voir le contenu du container: docker exec -it <id_container> bash remove container: docker container rm -f <id_container>","title":"Usefull docker command"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#synapps-environment","text":"check mps container : docker ps --filter \"name=mps\" or use this alias created : dpm docker stop run a service from the docker-compose file: docker-compose up -d <name_of_service> | example: docker-compose up -d mps-prod , docker-compose up -d app , ....","title":"Synapps environment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/","text":"This section will allow you to install a proper local environment step by step for Pilote application using VSCode IDE. VSCode Install VSCode Installation for VSCode can be found here: Installation of VSCode . Extensions Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension) User settings User settings for Ecolyo are described in this section: LINK TO SECTION TO ADD Git The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git . Node Version 12 For now please install node v12, any later version will cause side effects on sass modules! Download node-v12 Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Yarn Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn . Docker Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code. Install Docker Installation of Docker can be found here: Installation of Docker . Install Docker-Compose Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Setup your environment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#vscode","text":"","title":"VSCode"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-vscode","text":"Installation for VSCode can be found here: Installation of VSCode .","title":"Install VSCode"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#extensions","text":"Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension)","title":"Extensions"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#user-settings","text":"User settings for Ecolyo are described in this section: LINK TO SECTION TO ADD","title":"User settings"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#git","text":"The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git .","title":"Git"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#node","text":"Version 12 For now please install node v12, any later version will cause side effects on sass modules! Download node-v12 Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine.","title":"Node"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#yarn","text":"Yarn is used as package manager for this project. Feel free to use the one you prefere but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn .","title":"Yarn"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#docker","text":"Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.","title":"Docker"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-docker","text":"Installation of Docker can be found here: Installation of Docker .","title":"Install Docker"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-docker-compose","text":"Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Install Docker-Compose"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/","text":"Techno used NestJS Jest for the tests Docker PostgreSQL Docker-compose Two docker-compose are available into the project: - the general one - the local one For the general one, all service are details. The env variable used are available on Synapps server. The local one is used with the docker-compose_dev.yml","title":"Project Architecture"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/#techno-used","text":"NestJS Jest for the tests Docker PostgreSQL","title":"Techno used"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/#docker-compose","text":"Two docker-compose are available into the project: - the general one - the local one For the general one, all service are details. The env variable used are available on Synapps server. The local one is used with the docker-compose_dev.yml","title":"Docker-compose"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/application/deploy/","text":"Deployment For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline liked is running.","title":"Deploy"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/application/deploy/#deployment","text":"For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline liked is running.","title":"Deployment"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/","text":"This section explains the different functionalitites : Beneficiairies Once you are authenticated, you'll redirect into /liste-beneficiaire route. You are getting all usager known. Sharing For each beneficiary, you can ask the sharing. It means that you will be redirect into the public page of the cozy usager. In the same time, one process is running in order to send the sms. This sms contain one sharecode in order to provide some right on the cozy usager. In order to help you to understand this process, you can check : Pilote - TS - Back/project_architecture/share_sms.png","title":"Routes"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/#beneficiairies","text":"Once you are authenticated, you'll redirect into /liste-beneficiaire route. You are getting all usager known.","title":"Beneficiairies"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/#sharing","text":"For each beneficiary, you can ask the sharing. It means that you will be redirect into the public page of the cozy usager. In the same time, one process is running in order to send the sms. This sms contain one sharecode in order to provide some right on the cozy usager. In order to help you to understand this process, you can check : Pilote - TS - Back/project_architecture/share_sms.png","title":"Sharing"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial.git Installation of the project Start Pilote application Before to start Pilote application, you need to run this command in order to install dependencies: yarn install To start Pilote application just launch the command in a PowerShell or Windows Powershell tool: yarn start If the application starts successfully you should access to: http://localhost:3001/","title":"Launch the application on local"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial.git","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#start-pilote-application","text":"Before to start Pilote application, you need to run this command in order to install dependencies: yarn install To start Pilote application just launch the command in a PowerShell or Windows Powershell tool: yarn start If the application starts successfully you should access to: http://localhost:3001/","title":"Start Pilote application"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/","text":"Section under Construction This section will show you how to deploy your project on different environments. Setup First of all you'll need to install MobaXterm in order to connect to the server. Then, if you're on Linux you can skip the following section, otherwise if you are on Windows you'll have to install Windows Subsystem for Linux (WSL) since the deployment of the app is not working with windows commands. Install WSL First open Powershell as administrator and launch the following command : dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot . Install your Linux distribution After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 LTS). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list. Setup your distribution Start Up Updating the packages list by typing : sudo apt update Install the nodejs using the apt package manager sudo apt install To verify the Installation execute the following command : nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type : sudo apt install npm To verify the npm Install check using the command : npm --version To Downlaod and Setup Yarn sudo apt install yarn To check the Installed version of Yarn : yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands : sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on. Configuration of MobaXterm First open a new session and connect to the distant host 192.168.62.31 . Don't forget to add the path to the private key in the advanced SSH settings. Deploy Pilote Deploy on Alpha Windows First open your Ubuntu terminal, and clone the project in the repository of your choice. Once you've selected the branch of you want to deploy, write the following command : yarn build After this, you can launch the deployment. In order to deploy on pilote-dev-build (development environment) use the command : yarn deploy-dev If you want to deploy on the pilote-build environment, use : yarn deploy Linux From your current branch, run yarn build then sudo yarn deploy_dev to instantly deploy your working branch on the latest tagged Pilote container registry.","title":"Deploy"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#setup","text":"First of all you'll need to install MobaXterm in order to connect to the server. Then, if you're on Linux you can skip the following section, otherwise if you are on Windows you'll have to install Windows Subsystem for Linux (WSL) since the deployment of the app is not working with windows commands.","title":"Setup"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#install-wsl","text":"First open Powershell as administrator and launch the following command : dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot .","title":"Install WSL"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#install-your-linux-distribution","text":"After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 LTS). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list.","title":"Install your Linux distribution"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#setup-your-distribution","text":"Start Up Updating the packages list by typing : sudo apt update Install the nodejs using the apt package manager sudo apt install To verify the Installation execute the following command : nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type : sudo apt install npm To verify the npm Install check using the command : npm --version To Downlaod and Setup Yarn sudo apt install yarn To check the Installed version of Yarn : yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands : sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on.","title":"Setup your distribution"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#configuration-of-mobaxterm","text":"First open a new session and connect to the distant host 192.168.62.31 . Don't forget to add the path to the private key in the advanced SSH settings.","title":"Configuration of MobaXterm"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#deploy-pilote","text":"","title":"Deploy Pilote"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#deploy-on-alpha","text":"","title":"Deploy on Alpha"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#windows","text":"First open your Ubuntu terminal, and clone the project in the repository of your choice. Once you've selected the branch of you want to deploy, write the following command : yarn build After this, you can launch the deployment. In order to deploy on pilote-dev-build (development environment) use the command : yarn deploy-dev If you want to deploy on the pilote-build environment, use : yarn deploy","title":"Windows"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#linux","text":"From your current branch, run yarn build then sudo yarn deploy_dev to instantly deploy your working branch on the latest tagged Pilote container registry.","title":"Linux"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/","text":"Doctypes Doctypes represent different types of data. Their primary use is for permissions: an app or konnector will request permissions for one or several doctypes and will not be able to access other doctypes. See Doctypes documentation for more information. The following is a full description of the doctypes we use and their fields. Cozy doctypes won't be fully described. Instead, for every used one, we'll include a link to its official documentation. Used Cozy doctypes io.cozy.accounts : Konnector accounts io.cozy.apps : Installed apps io.cozy.contacts : Contacts io.cozy.contacts.groups : Contacts groups io.cozy.files : Files io.cozy.permissions : Permissions of the instance io.cozy.konnectors : Konnectors io.cozy.triggers : Job triggers Used Cozy remote doctypes This kind of doctype are set from the team. We have push two remote doctypes (each duplicate for rec and prod environment) Prod - [ org.mps.store ]: Required for store information on back-endTS - [ org.mps.share ]: Required for searching on back-endTS Recette [ org.mps.store.rec ]: Required for store information on rec back-endTS [ org.mps.share.rec ]: Required for searching on rec back-endTS If you need to target rec remote doctype, you need to change the request : client.getStackClient().fetchJSON('POST','...') and change them into the manifest also. Custom doctypes com.grandlyon.mps.profile ##### Attributes tutorial : { object } contains contacts , documents , actions , and notes . They represent the state of tutorials. For example, contacts: true means the contacts tutorial hasn't been seen yet and will be visible to the user the next time he visits the contacts component. notification : { boolean } If equals true, the user has a notification fullname : { string } User's full name introduction : { boolean } If equals true , it means the user has already used the app and seen the introduction. lastConnectionDate : { string } When was the user last connected (ISO string). hasPhone : { boolean } Equals true if the current user has already a phone number userID : { string } Current user id publicProfile : { object } contains fullname , endDate (ISO string), and isActive com.grandlyon.mps.appointments ##### Attributes id : { string } the appointment id appointmentDate : { string } the appointment date (ISO string) note : { Note } A unique note for each appointment objectives : { Array<Objective> } The list of appointment's objectives com.grandlyon.mps.objectives ##### Attributes id : { string } the objective id title : { string } the objective title type : { string } The id of the Objective type subtype : { string } The id of the Objective subType tasks : { Array<Task> } Array of Tasks ids archived : { boolean } If equals true, it mean the objective has been completed com.grandlyon.mps.tasks ##### Attributes id : { string } The task id name : { string } The task name description : { string } The task description state : { TaskState } It could be one of the following: 'USER_TO_VALID', 'USER_VALID', 'PUBLIC_VALID', 'PUBLIC_INVALID' qualifications : { Array<string> } items : { Array<TaskItem> } com.grandlyon.mps.task.items ##### Attributes id : { string } Item id file : { DocumentEntity } The items' file state : { TaskItemState } It could be one of the following: 'USER_ITEM_PENDING', 'PUBLIC_ITEM_VALID', 'PUBLIC_ITEM_INVALID' com.grandlyon.mps.notes ##### Attributes id : { string } Note's id content : { string } The content of the note. createdAt : { string } Date of creation (ISO string)","title":"Doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#doctypes","text":"Doctypes represent different types of data. Their primary use is for permissions: an app or konnector will request permissions for one or several doctypes and will not be able to access other doctypes. See Doctypes documentation for more information. The following is a full description of the doctypes we use and their fields. Cozy doctypes won't be fully described. Instead, for every used one, we'll include a link to its official documentation.","title":"Doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#used-cozy-doctypes","text":"io.cozy.accounts : Konnector accounts io.cozy.apps : Installed apps io.cozy.contacts : Contacts io.cozy.contacts.groups : Contacts groups io.cozy.files : Files io.cozy.permissions : Permissions of the instance io.cozy.konnectors : Konnectors io.cozy.triggers : Job triggers","title":"Used Cozy doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#used-cozy-remote-doctypes","text":"This kind of doctype are set from the team. We have push two remote doctypes (each duplicate for rec and prod environment) Prod - [ org.mps.store ]: Required for store information on back-endTS - [ org.mps.share ]: Required for searching on back-endTS Recette [ org.mps.store.rec ]: Required for store information on rec back-endTS [ org.mps.share.rec ]: Required for searching on rec back-endTS If you need to target rec remote doctype, you need to change the request : client.getStackClient().fetchJSON('POST','...') and change them into the manifest also.","title":"Used Cozy remote doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#custom-doctypes","text":"com.grandlyon.mps.profile ##### Attributes tutorial : { object } contains contacts , documents , actions , and notes . They represent the state of tutorials. For example, contacts: true means the contacts tutorial hasn't been seen yet and will be visible to the user the next time he visits the contacts component. notification : { boolean } If equals true, the user has a notification fullname : { string } User's full name introduction : { boolean } If equals true , it means the user has already used the app and seen the introduction. lastConnectionDate : { string } When was the user last connected (ISO string). hasPhone : { boolean } Equals true if the current user has already a phone number userID : { string } Current user id publicProfile : { object } contains fullname , endDate (ISO string), and isActive com.grandlyon.mps.appointments ##### Attributes id : { string } the appointment id appointmentDate : { string } the appointment date (ISO string) note : { Note } A unique note for each appointment objectives : { Array<Objective> } The list of appointment's objectives com.grandlyon.mps.objectives ##### Attributes id : { string } the objective id title : { string } the objective title type : { string } The id of the Objective type subtype : { string } The id of the Objective subType tasks : { Array<Task> } Array of Tasks ids archived : { boolean } If equals true, it mean the objective has been completed com.grandlyon.mps.tasks ##### Attributes id : { string } The task id name : { string } The task name description : { string } The task description state : { TaskState } It could be one of the following: 'USER_TO_VALID', 'USER_VALID', 'PUBLIC_VALID', 'PUBLIC_INVALID' qualifications : { Array<string> } items : { Array<TaskItem> } com.grandlyon.mps.task.items ##### Attributes id : { string } Item id file : { DocumentEntity } The items' file state : { TaskItemState } It could be one of the following: 'USER_ITEM_PENDING', 'PUBLIC_ITEM_VALID', 'PUBLIC_ITEM_INVALID' com.grandlyon.mps.notes ##### Attributes id : { string } Note's id content : { string } The content of the note. createdAt : { string } Date of creation (ISO string)","title":"Custom doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/","text":"Initialize Create a new project in GitLab and take note of its URL Protecting Master Branch On the GitLab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be merge requests. Setting Development Branch Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev Start Developing For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch Conventional Commits A feature branch name should follow this structure: feat/<title_of_the_user_story> You can create the branch by typing: git checkout -b feat/<title_of_the_user_story> Each fix branch should be named as the following fix-\\<title_of_the_fix> . Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Gitflow"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#initialize","text":"Create a new project in GitLab and take note of its URL","title":"Initialize"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#protecting-master-branch","text":"On the GitLab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be merge requests.","title":"Protecting Master Branch"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#setting-development-branch","text":"Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev","title":"Setting Development Branch"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#start-developing","text":"For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch","title":"Start Developing"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#conventional-commits","text":"A feature branch name should follow this structure: feat/<title_of_the_user_story> You can create the branch by typing: git checkout -b feat/<title_of_the_user_story> Each fix branch should be named as the following fix-\\<title_of_the_fix> . Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Conventional Commits"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/","text":"Scaffolding In this section, you will find information about the project file structure and the purpose of main folders and files. Source Files Folder/File Purpose assets The application's assets, contains fonts, SVGs, PNGs, and GIFs. doctypes Contains the cozy doctypes, you can see more on Cozy Documentation . helpers Contains helper functions that are used by services. It contains also a test file for each helper file. locales Contains JSON data used by the translation system i18n provided by Cozy-ui . models Contains all our models' Interfaces services Here you'll find all the services. It contains also a test file for each service file. store Redux store. Contains actions, reducers, and store types. styles Styles folder. The base folder under it contains our variables, fonts, breakpoints, animations, and mixins. Whenever you add a style file elsewhere, don't forget to import it in index.scss . targets Contains mobile and browser targets. It also contains a Public target for the service worker . types Contains all cozy types. utils In this folder you'll find utilities methods. components/App.tsx The root component. Configuration Files File Purpose .editorconfig Editor config rules .eslintrc.js ESLint config file gitlab-ci.yml Gitlab continuous integration config file .prettierrc Prettier extension config file app.config.* Overloads webpack configuration jest.config.js Jest config file manifest.webapp Manifest of the application, used by cozy for permissions' management. You can add permissions for doctypes here tsconfig.json TypeScript config file konnector-dev-config.json To locally test konnectors service-dev-config.json To locally test services","title":"Scaffolding"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#scaffolding","text":"In this section, you will find information about the project file structure and the purpose of main folders and files.","title":"Scaffolding"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#source-files","text":"Folder/File Purpose assets The application's assets, contains fonts, SVGs, PNGs, and GIFs. doctypes Contains the cozy doctypes, you can see more on Cozy Documentation . helpers Contains helper functions that are used by services. It contains also a test file for each helper file. locales Contains JSON data used by the translation system i18n provided by Cozy-ui . models Contains all our models' Interfaces services Here you'll find all the services. It contains also a test file for each service file. store Redux store. Contains actions, reducers, and store types. styles Styles folder. The base folder under it contains our variables, fonts, breakpoints, animations, and mixins. Whenever you add a style file elsewhere, don't forget to import it in index.scss . targets Contains mobile and browser targets. It also contains a Public target for the service worker . types Contains all cozy types. utils In this folder you'll find utilities methods. components/App.tsx The root component.","title":"Source Files"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#configuration-files","text":"File Purpose .editorconfig Editor config rules .eslintrc.js ESLint config file gitlab-ci.yml Gitlab continuous integration config file .prettierrc Prettier extension config file app.config.* Overloads webpack configuration jest.config.js Jest config file manifest.webapp Manifest of the application, used by cozy for permissions' management. You can add permissions for doctypes here tsconfig.json TypeScript config file konnector-dev-config.json To locally test konnectors service-dev-config.json To locally test services","title":"Configuration Files"},{"location":"pilote/Pilote%20-%20Usager/application/services/","text":"Profile Service Functions getProfile : Tries fetching the profile if it exists. If not, it creates a new one and returns it. updateProfile : Updates the profile. parseProfile : Returns the Profile passed as a parameter without the following properties: _id, id, _type, _rev, cozyMetadata . Notes Service Functions parseNote : Returns the Note passed as a parameter without the following properties: _id, _type, _rev, cozyMetadata . getNoteByIDs : Returns a list of Notes from a list of ids. createNote : Creates a new Note. updateNote : Updates a Note. getCurrentNoteOrCreate : Returns the Note linked to the current Appointment. If id does not exist, it creates and returns a new one. getAllNotes : Returns a list of all Notes. Appointments Service Functions parseAppointment : Returns an Appointment from an AppointmentEntity. getLastAppointment : Returns the last Appointment, which a user can see first in /actions. getAllAppointment : returns a list of all Appointments. getAppointmentByID : Returns an Appointment from its id. createAppointment : Creates a new Appointment. updateAppointment : Updates an Appointment. Documents Service Functions getAllDocuments : Returns the list of all documents. getDocumentsByQualification : Returns a document by a qualification. getDocumentsByQualifications : Uses getDocumentsByQualification to return a list of documents from a list of qualifications. getDocumentByID : Returns a document by its id. saveDocument : Creates a new file. editDocumentName : Edits a document's name by its id. deleteDocumentById : Deletes the document by its id. downloadDocument : Downloads a file from its id. downloadArchive : Downloads an archive containing all the files whom ids are passed as a parameter. getLinkDoc : Returns the file download link. getReferencedFolders : Gets a folder by a reference. getOrCreateFolderWithReference : Gets a folder by a reference or creates it if it does not exist. getDocumentsWithQualifications : Returns the qualified documents along with the not qualified ones ( { qualified, other } ). replaceFile : Replaces a file. keepFile : Changes a file's name and saves it. Contacts Service Functions getCurrentUser : Returns the contact with an existing me field, which represents the current user. getAllContacts : Returns a list of all contacts. findContactById : Returns a contact by its id. createContact : Creates a new contact. updateContact : Updates an existing contact. deleteContactById : Deletes a contact by its id. Groups Service Function createMetroGroup : Creates a new group and returns it. getMetroGroup : Returns the group if it exists or creates it if it doesn't. Initialization Service Initialization : { Object } Initializes the profile, actions, and the appDirectory. Konnectors Service Functions getAllKonnectors : Returns a list of all the Konnectors. getAllKonnectorSlugs : Returns a list of all the Konnectors' slugs. getKonnectorNameBySlug : Returns a Konnector name from a slug. getKonnectorBySlug : Returns a Konnector from a slug. getKonnectorByName : Returns a Konnector from its name. getKonnectorsFromDocuments : Returns a list of Konnectors from a passed DocumentEntity list. Objectives Service Functions parseObjective : Returns the Objective passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getObjectiveByIDs : Returns a list of Objectives from a list of ids. getOldObjectives : Returns a list of the archived Objectives not belonging to the last Appointment. createObjective : Creates a new Objective. updateObjective : Updates an existing Objective. Tasks Service Functions parseTaskJSONToTask : Returns a Task from a TaskJSON. parseTask : Returns the Task passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTasksByIDs : Returns a list of Tasks from a list of ids. createTask : Creates a new Task. updateTask : Updates a Task from its id. TaskItems Service Functions parseTaskItem : Returns the TaskItem passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTaskItemByIDs : Returns a list of TaskItems from a list of ids. createTaskItem : Creates a new TaskItem. updateTaskItem : Updates a TaskItem from its id. Triggers Service Functions getAllTriggers : Returns All the triggers filtred by type if passed as parameter.","title":"Services"},{"location":"pilote/Pilote%20-%20Usager/application/services/#profile-service","text":"","title":"Profile Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions","text":"getProfile : Tries fetching the profile if it exists. If not, it creates a new one and returns it. updateProfile : Updates the profile. parseProfile : Returns the Profile passed as a parameter without the following properties: _id, id, _type, _rev, cozyMetadata .","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#notes-service","text":"","title":"Notes Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_1","text":"parseNote : Returns the Note passed as a parameter without the following properties: _id, _type, _rev, cozyMetadata . getNoteByIDs : Returns a list of Notes from a list of ids. createNote : Creates a new Note. updateNote : Updates a Note. getCurrentNoteOrCreate : Returns the Note linked to the current Appointment. If id does not exist, it creates and returns a new one. getAllNotes : Returns a list of all Notes.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#appointments-service","text":"","title":"Appointments Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_2","text":"parseAppointment : Returns an Appointment from an AppointmentEntity. getLastAppointment : Returns the last Appointment, which a user can see first in /actions. getAllAppointment : returns a list of all Appointments. getAppointmentByID : Returns an Appointment from its id. createAppointment : Creates a new Appointment. updateAppointment : Updates an Appointment.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#documents-service","text":"","title":"Documents Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_3","text":"getAllDocuments : Returns the list of all documents. getDocumentsByQualification : Returns a document by a qualification. getDocumentsByQualifications : Uses getDocumentsByQualification to return a list of documents from a list of qualifications. getDocumentByID : Returns a document by its id. saveDocument : Creates a new file. editDocumentName : Edits a document's name by its id. deleteDocumentById : Deletes the document by its id. downloadDocument : Downloads a file from its id. downloadArchive : Downloads an archive containing all the files whom ids are passed as a parameter. getLinkDoc : Returns the file download link. getReferencedFolders : Gets a folder by a reference. getOrCreateFolderWithReference : Gets a folder by a reference or creates it if it does not exist. getDocumentsWithQualifications : Returns the qualified documents along with the not qualified ones ( { qualified, other } ). replaceFile : Replaces a file. keepFile : Changes a file's name and saves it.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#contacts-service","text":"","title":"Contacts Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_4","text":"getCurrentUser : Returns the contact with an existing me field, which represents the current user. getAllContacts : Returns a list of all contacts. findContactById : Returns a contact by its id. createContact : Creates a new contact. updateContact : Updates an existing contact. deleteContactById : Deletes a contact by its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#groups-service","text":"","title":"Groups Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#function","text":"createMetroGroup : Creates a new group and returns it. getMetroGroup : Returns the group if it exists or creates it if it doesn't.","title":"Function"},{"location":"pilote/Pilote%20-%20Usager/application/services/#initialization-service","text":"Initialization : { Object } Initializes the profile, actions, and the appDirectory.","title":"Initialization Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#konnectors-service","text":"","title":"Konnectors Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_5","text":"getAllKonnectors : Returns a list of all the Konnectors. getAllKonnectorSlugs : Returns a list of all the Konnectors' slugs. getKonnectorNameBySlug : Returns a Konnector name from a slug. getKonnectorBySlug : Returns a Konnector from a slug. getKonnectorByName : Returns a Konnector from its name. getKonnectorsFromDocuments : Returns a list of Konnectors from a passed DocumentEntity list.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#objectives-service","text":"","title":"Objectives Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_6","text":"parseObjective : Returns the Objective passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getObjectiveByIDs : Returns a list of Objectives from a list of ids. getOldObjectives : Returns a list of the archived Objectives not belonging to the last Appointment. createObjective : Creates a new Objective. updateObjective : Updates an existing Objective.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#tasks-service","text":"","title":"Tasks Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_7","text":"parseTaskJSONToTask : Returns a Task from a TaskJSON. parseTask : Returns the Task passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTasksByIDs : Returns a list of Tasks from a list of ids. createTask : Creates a new Task. updateTask : Updates a Task from its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#taskitems-service","text":"","title":"TaskItems Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_8","text":"parseTaskItem : Returns the TaskItem passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTaskItemByIDs : Returns a list of TaskItems from a list of ids. createTaskItem : Creates a new TaskItem. updateTaskItem : Updates a TaskItem from its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#triggers-service","text":"","title":"Triggers Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_9","text":"getAllTriggers : Returns All the triggers filtred by type if passed as parameter.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/store/","text":"Redux We are using Redux for our application state management. it maintains the state of the entire application in a single immutable state tree (object), which can't be changed directly. When something changes, a new object is created (using actions and reducers). For more information about Redux, visit The [official documentation][https://redux.js.org/]. Store The following are the existing store entities used by our application: Profile : Preserves the state of tutorials, user profile, public profile, introduction, and notifications (see initial state below). Global : Preserves the global state, which includes isPublic toast and error Appointment : Preserves the state of tutorials and notifications. UploadDocument : Manages the state of uploaded documents. Initial states Profile { tutorial : { // Tells if a tutorial has already been seen contacts : true , documents : true , actions : { first : true , // 'first' represents the actions component with no appointments yet second : true , // 'second' represents the actions component with an existing appointment }, }, fullname : '' , introduction : true , // If 'true', the user has already used the app and seen the introduction notification : false , lastConnectionDate : '' , // ISO string hasPhone : false , userID : '' , publicProfile : { fullname : '' , endDate : '' , // Timestamp isActive : false , }, } Global { isPublic : false , toast : null , // Manages global messages toasts error : false , // Manages global errors } Appointment { id : '' , appointmentDate : '' , // ISO string note : { id : '' , content : '' , createdAt : '' , // ISO string }, objectives : [], } UploadDocument { file : null , qualification : null , } For each reducer file, a test file is associated testing the reducer. All the actions are tested in a separate file with the same actions file name. Used packages react-redux : Official React bindings for Redux . react-redux : Thunk middleware for Redux. redux-devtools-extension : For application's state changes debugging. @types/react-redux : This package contains type definitions for react-redux.","title":"Store"},{"location":"pilote/Pilote%20-%20Usager/application/store/#redux","text":"We are using Redux for our application state management. it maintains the state of the entire application in a single immutable state tree (object), which can't be changed directly. When something changes, a new object is created (using actions and reducers). For more information about Redux, visit The [official documentation][https://redux.js.org/].","title":"Redux"},{"location":"pilote/Pilote%20-%20Usager/application/store/#store","text":"The following are the existing store entities used by our application: Profile : Preserves the state of tutorials, user profile, public profile, introduction, and notifications (see initial state below). Global : Preserves the global state, which includes isPublic toast and error Appointment : Preserves the state of tutorials and notifications. UploadDocument : Manages the state of uploaded documents.","title":"Store"},{"location":"pilote/Pilote%20-%20Usager/application/store/#initial-states","text":"","title":"Initial states"},{"location":"pilote/Pilote%20-%20Usager/application/store/#profile","text":"{ tutorial : { // Tells if a tutorial has already been seen contacts : true , documents : true , actions : { first : true , // 'first' represents the actions component with no appointments yet second : true , // 'second' represents the actions component with an existing appointment }, }, fullname : '' , introduction : true , // If 'true', the user has already used the app and seen the introduction notification : false , lastConnectionDate : '' , // ISO string hasPhone : false , userID : '' , publicProfile : { fullname : '' , endDate : '' , // Timestamp isActive : false , }, }","title":"Profile"},{"location":"pilote/Pilote%20-%20Usager/application/store/#global","text":"{ isPublic : false , toast : null , // Manages global messages toasts error : false , // Manages global errors }","title":"Global"},{"location":"pilote/Pilote%20-%20Usager/application/store/#appointment","text":"{ id : '' , appointmentDate : '' , // ISO string note : { id : '' , content : '' , createdAt : '' , // ISO string }, objectives : [], }","title":"Appointment"},{"location":"pilote/Pilote%20-%20Usager/application/store/#uploaddocument","text":"{ file : null , qualification : null , } For each reducer file, a test file is associated testing the reducer. All the actions are tested in a separate file with the same actions file name.","title":"UploadDocument"},{"location":"pilote/Pilote%20-%20Usager/application/store/#used-packages","text":"react-redux : Official React bindings for Redux . react-redux : Thunk middleware for Redux. redux-devtools-extension : For application's state changes debugging. @types/react-redux : This package contains type definitions for react-redux.","title":"Used packages"},{"location":"pilote/Pilote%20-%20Usager/functionalities/appointments/","text":"This section explain all the functionnalities in the appointment part","title":"Appointments"},{"location":"pilote/Pilote%20-%20Usager/functionalities/contact/","text":"Description Pilote allow usager to add contact : - You will always see your profil at the first contact. You can not delete it. Just edit it. - Then, with the add concat button, you can add others contact","title":"Contact"},{"location":"pilote/Pilote%20-%20Usager/functionalities/contact/#description","text":"Pilote allow usager to add contact : - You will always see your profil at the first contact. You can not delete it. Just edit it. - Then, with the add concat button, you can add others contact","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/","text":"Description Pilote Usager is linked to a registry to allow a TS to find and connect to a user Pilote app. A service is run every day to send instance information to the registry. Service Flow summarized Launch the service locally Switch to Node 16 (using nvm or n) install local remote doctypes (details here ), add a folder named org.mps.registry.dev, inside it add a file named request with the following content : POST https://cozy-registry.poc.self-data.alpha.grandlyon.com/api/pilote Authorization: Bearer {{secret_token}} Content-Type: application/json {{data}} in the database, if it doesn't exist, create a table named secrets/io-cozy-remote-secrets and add a document with the following content : { \"_id\" : \"org.mps.registry.dev\" , \"token\" : \"pilotecozytoken\" } launch docker-compose up in a first terminal launch yarn build in a second terminal launch yarn run cozy-konnector-dev -m ./manifest.webapp ./build/services/cozyRegistry/pilote.js to execute the service","title":"Cozy Registry"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#description","text":"Pilote Usager is linked to a registry to allow a TS to find and connect to a user Pilote app. A service is run every day to send instance information to the registry.","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#service-flow-summarized","text":"","title":"Service Flow summarized"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#launch-the-service-locally","text":"Switch to Node 16 (using nvm or n) install local remote doctypes (details here ), add a folder named org.mps.registry.dev, inside it add a file named request with the following content : POST https://cozy-registry.poc.self-data.alpha.grandlyon.com/api/pilote Authorization: Bearer {{secret_token}} Content-Type: application/json {{data}} in the database, if it doesn't exist, create a table named secrets/io-cozy-remote-secrets and add a document with the following content : { \"_id\" : \"org.mps.registry.dev\" , \"token\" : \"pilotecozytoken\" } launch docker-compose up in a first terminal launch yarn build in a second terminal launch yarn run cozy-konnector-dev -m ./manifest.webapp ./build/services/cozyRegistry/pilote.js to execute the service","title":"Launch the service locally"},{"location":"pilote/Pilote%20-%20Usager/functionalities/document/","text":"This section explains how to handle data storage.","title":"Document"},{"location":"pilote/Pilote%20-%20Usager/functionalities/setting/","text":"Description Pilote has setting page. You can found : - Notifications: Under construction - Tutorial: allow to view again one of the tutorial available - FAQ: Different explication of the global application - Legal Notice","title":"Settings"},{"location":"pilote/Pilote%20-%20Usager/functionalities/setting/#description","text":"Pilote has setting page. You can found : - Notifications: Under construction - Tutorial: allow to view again one of the tutorial available - FAQ: Different explication of the global application - Legal Notice","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use the following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager Installation of the project Start Pilote Usager application Before starting Pilote Usager application, you need to install dependencies: yarn install To start Pilote Usager application, you first need start the application and start a cozy stack: yarn start docker-compose up stack As the pilote application has been recently upgraded to NodeJS 16 version, you might need to install additionnal packages in order to be able to run the app. Make sure your have the following installed : Python3 Microsoft Visual Studio tools 2017 node-gyp And wait for the success message. Everything is setup. Go to http://pilote.cozy.tools:8080/ Once successful you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '. Start Pilote TS application To start a social worker instance, go to options page and click ' Get sharecode '. Open the console and you'll see a link redirecting to a TS instance.","title":"Launch local application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#clone-the-project-repository","text":"Use the following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#start-pilote-usager-application","text":"Before starting Pilote Usager application, you need to install dependencies: yarn install To start Pilote Usager application, you first need start the application and start a cozy stack: yarn start docker-compose up stack As the pilote application has been recently upgraded to NodeJS 16 version, you might need to install additionnal packages in order to be able to run the app. Make sure your have the following installed : Python3 Microsoft Visual Studio tools 2017 node-gyp And wait for the success message. Everything is setup. Go to http://pilote.cozy.tools:8080/ Once successful you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '.","title":"Start Pilote Usager application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#start-pilote-ts-application","text":"To start a social worker instance, go to options page and click ' Get sharecode '. Open the console and you'll see a link redirecting to a TS instance.","title":"Start Pilote TS application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/","text":"Use cozy-doctype in local In order to be able to use our own cozy-doctype, especialy remote doctype here, we need to use them in local. 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes warning You need to build and push the newlest image on the forge registry when the step 3 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! For this project: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 4/ The path \"/data/cozy-doctypes\" is linked to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes How to test your remote doctype ? GET 1/ In the request file created. Specify the method and the route to your target URL : GET https://pilote-agent-dev.grandlyon.com/api/cozy or with value in query : GET https://pilote-agent-dev.grandlyon.com/api/auth/token/check?token={{token}} 2/ Then, you can test it by : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share') or with value in query : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2OTI0NjYsImV4cCI6MTYwNTY5MjUyNn0.HbQh5H-TcVIASUpbjZAD0MY9slRAJOVw-VMKSBu_sQ0' ) POST 1/ In the request file created. Specify the methode and the route to your target URL : POST https://pilote-agent-dev.grandlyon.com/api/auth/token/check Content-Type: application/json {{data}} 2/ Then, you can test it by : const parameters = { data: JSON.stringify({ token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2MjYxNzAsImV4cCI6MTYwNTYyNjIzMH0.8m-rEAZkuqb4upAPKY7j8DhvFi8mVbmiCFDitgNYt6Y\" } ) } console.log('call remote ==> ', await client.getStackClient().fetchJSON('POST','/remote/org.mps.share', parameters ))","title":"Launch local doctypes"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#use-cozy-doctype-in-local","text":"In order to be able to use our own cozy-doctype, especialy remote doctype here, we need to use them in local. 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes warning You need to build and push the newlest image on the forge registry when the step 3 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! For this project: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 4/ The path \"/data/cozy-doctypes\" is linked to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes","title":"Use cozy-doctype in local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#how-to-test-your-remote-doctype","text":"","title":"How to test your remote doctype ?"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#get","text":"1/ In the request file created. Specify the method and the route to your target URL : GET https://pilote-agent-dev.grandlyon.com/api/cozy or with value in query : GET https://pilote-agent-dev.grandlyon.com/api/auth/token/check?token={{token}} 2/ Then, you can test it by : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share') or with value in query : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2OTI0NjYsImV4cCI6MTYwNTY5MjUyNn0.HbQh5H-TcVIASUpbjZAD0MY9slRAJOVw-VMKSBu_sQ0' )","title":"GET"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#post","text":"1/ In the request file created. Specify the methode and the route to your target URL : POST https://pilote-agent-dev.grandlyon.com/api/auth/token/check Content-Type: application/json {{data}} 2/ Then, you can test it by : const parameters = { data: JSON.stringify({ token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2MjYxNzAsImV4cCI6MTYwNTYyNjIzMH0.8m-rEAZkuqb4upAPKY7j8DhvFi8mVbmiCFDitgNYt6Y\" } ) } console.log('call remote ==> ', await client.getStackClient().fetchJSON('POST','/remote/org.mps.share', parameters ))","title":"POST"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/","text":"Use services in local Configure the cozy-stack on local In order to be able to use your sercice, follow these steps: 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes 4/ You need to add another option when you install apps in the cozy-stack (go to: docker\\cozy-app-dev-with-app.sh) In do_install_app(): #add symbolic link to mps for sms service ln -s /data/cozy-app/mps /data/cozy-storage/cozy.tools\\:8080/.cozy_apps/mps if [ -d \"data/cozy-app/mps/0.1.1\" ]; then echo \"data/cozy-app/mps/0.1.1 already here!\"; else mkdir /data/cozy-app/mps/0.1.1 cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"data/cozy-app/mps/0.1.1 just create!\"; fi # mkdir /data/cozy-app/mps/0.1.1 # cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"service added\" 5/ Then, add konnector-node-run.sh in docker folder. This file is a script to store the service logs. It should contain: #!/bin/bash rundir=\"${1}\" cd $rundir node index.js | tee /data/cozy-app/mps/services.log Then, add this following row into the Dockerfile: COPY konnector-node-run.sh /etc/cozy/konnector-node-run.sh 6/ Into the disableCSP.yml, you need to add one more configuration: konnectors: cmd: /etc/cozy/konnector-node-run.sh # run connectors with node warning You need to build and push the newlest image on the forge registry when the step 6 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! Finaly, you should rebuild the docker image of the cozy-stack: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 7/ The path \"/data/cozy-doctypes\" is link to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes How to test your service ? In the manifest.webapp, you need to declare the service: \"services\": { \"smsProcess\": { \"type\": \"node\", \"file\": \"services/smsProcess/pilote.js\" } }, Then, in src\\targets\\services, you can add your service. For this project, we have created a button in Home.component.tsx in order to generate trigger url to run the service: const getTrigger = async () => { const attrs = { type: '@webhook', worker: 'service', message: { name: 'smsProcess', slug: 'pilotedemo', }, } const trigger = await client.getStackClient() .collection('io.cozy.triggers') .create(attrs) console.log('trigger', trigger) } It generates an trigger URL that we can call with our backend application : URL_COZY/job/webhook/{{trigger_id}} URL_COZY represent the cozy-stack url of your environment and not your application URL.","title":"Launch local services"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#use-services-in-local","text":"","title":"Use services in local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#configure-the-cozy-stack-on-local","text":"In order to be able to use your sercice, follow these steps: 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes 4/ You need to add another option when you install apps in the cozy-stack (go to: docker\\cozy-app-dev-with-app.sh) In do_install_app(): #add symbolic link to mps for sms service ln -s /data/cozy-app/mps /data/cozy-storage/cozy.tools\\:8080/.cozy_apps/mps if [ -d \"data/cozy-app/mps/0.1.1\" ]; then echo \"data/cozy-app/mps/0.1.1 already here!\"; else mkdir /data/cozy-app/mps/0.1.1 cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"data/cozy-app/mps/0.1.1 just create!\"; fi # mkdir /data/cozy-app/mps/0.1.1 # cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"service added\" 5/ Then, add konnector-node-run.sh in docker folder. This file is a script to store the service logs. It should contain: #!/bin/bash rundir=\"${1}\" cd $rundir node index.js | tee /data/cozy-app/mps/services.log Then, add this following row into the Dockerfile: COPY konnector-node-run.sh /etc/cozy/konnector-node-run.sh 6/ Into the disableCSP.yml, you need to add one more configuration: konnectors: cmd: /etc/cozy/konnector-node-run.sh # run connectors with node warning You need to build and push the newlest image on the forge registry when the step 6 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! Finaly, you should rebuild the docker image of the cozy-stack: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 7/ The path \"/data/cozy-doctypes\" is link to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes","title":"Configure the cozy-stack on local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#how-to-test-your-service","text":"In the manifest.webapp, you need to declare the service: \"services\": { \"smsProcess\": { \"type\": \"node\", \"file\": \"services/smsProcess/pilote.js\" } }, Then, in src\\targets\\services, you can add your service. For this project, we have created a button in Home.component.tsx in order to generate trigger url to run the service: const getTrigger = async () => { const attrs = { type: '@webhook', worker: 'service', message: { name: 'smsProcess', slug: 'pilotedemo', }, } const trigger = await client.getStackClient() .collection('io.cozy.triggers') .create(attrs) console.log('trigger', trigger) } It generates an trigger URL that we can call with our backend application : URL_COZY/job/webhook/{{trigger_id}} URL_COZY represent the cozy-stack url of your environment and not your application URL.","title":"How to test your service ?"},{"location":"proxy/description/","text":"This section of documentation refers to the Oauth protocols working hand in hand with our custom proxy and the cozy-stack. To fully understand its whereabouts, you should also look at the enedis konnector and grdf konnector documentation. proxy code source Feel free to check the proxy code at all time when reading this documentation. Oauth Dance To access customer data, one must first obtain customer authorization. This authorization is materialized by an access token and it must be obtained by the APIs exposed by each energy providers. These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent. See both Enedis and Grdf use cases before going further. Cozy Oauth Protocol cozy oauth flow documentation https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow Couchdb The couchdb database must hold all informations needed for the konnector authentication to work properly. Auth informations are stored in the secrets/io-cozy-account_types database. You can create manually the document by entering these parameters for each konnector: Name Description _id Name of your konnector, for instance: enedisgrandlyon grant_mode authorization_code client_id Application id given by the API provider client_secret Secret also given by the API provider auth_endpoint Authorize endpoint to request when starting the oauth protocol token_endpoint Token endpoint to request, will be called when the auth endpoint response reaches the stack token_mode get Once the document is created, when launching the konnector from the cozy-home or inside the running application. The oauth flow will start. The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step. If the token request is a success. An account/service-name database will be added in couchdb containing all informations needed for authentication and the konnector will be free to work on all endpoints within its scope. Why we Need a Proxy The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personnal clouds, following this guideline would mean that we need a client_id and a client_secret for each one of all the applications running. To answer this issue, two solutions are possible depending on what the energy supplier is willing to do. Providers could allow wildcard subdomains when registering the callback URI, it would parse the subdomain and adapt its redirection when answering /auth call. Example: https//*.cozygrandlyon.cloud/account/redirect -> parse subdomain before .cozy xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz toto.cozygrandlyon.cloud/account/redirect -> redirect to toto If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirections. Result With that in mind, the proxy is now the one calling the auth and token provider endpoints. The instance name will be contained in redirect_uri, the stack will insert this parameters by itself in the /auth call. 3 endpoints are created in the proxy for each energy supplier : One for the auth One for the token One for the redirect uri Proxy flow Proxy Code Explained reminder Feel free to check the proxy code at all time when reading this documentation. The proxy is coded in golang. It is composed of six endpoints as seen above. The first endpoint to be called is /auth . auth Originally called from a cozy-stack trying to setup its konnector. The proxy gets these informations from the query: client_id duration redirect_uri (auto inserted by the cozy-stack, except if you specify skip_redirect_uri:true in the couchdb) response_type state (as it was conceived by the cozy-stack) The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling. With all these informations, the proxy can contact the provider /auth endpoint to start the oauth dance. Enedis note See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the cozyOrigin instance name. This will be usefull when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer. Once the call is sent, enedis will point to the /redirect endpoint. Grdf To be redacted redirect Retrieve the code , usage_point_id , and state answered by Enedis. Split the customed state that was modified in the /auth process. From this split it creates two variables : state host Finally redirect all these parameters in a query to the cozy-stack (the cozy-stack which is still waiting for an answer from its /auth call). state / instance The state must be recovered without the instance name, otherwise the cozy-stack won't recognized it and the handshake will fail. token Gathering from query or parameters all params. Sends a post request to the provider /token endpoint. The stack will store the response params in a accounts couchdb database.","title":"Description"},{"location":"proxy/description/#oauth-dance","text":"To access customer data, one must first obtain customer authorization. This authorization is materialized by an access token and it must be obtained by the APIs exposed by each energy providers. These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent. See both Enedis and Grdf use cases before going further.","title":"Oauth Dance"},{"location":"proxy/description/#cozy-oauth-protocol","text":"cozy oauth flow documentation https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow","title":"Cozy Oauth Protocol"},{"location":"proxy/description/#couchdb","text":"The couchdb database must hold all informations needed for the konnector authentication to work properly. Auth informations are stored in the secrets/io-cozy-account_types database. You can create manually the document by entering these parameters for each konnector: Name Description _id Name of your konnector, for instance: enedisgrandlyon grant_mode authorization_code client_id Application id given by the API provider client_secret Secret also given by the API provider auth_endpoint Authorize endpoint to request when starting the oauth protocol token_endpoint Token endpoint to request, will be called when the auth endpoint response reaches the stack token_mode get Once the document is created, when launching the konnector from the cozy-home or inside the running application. The oauth flow will start. The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step. If the token request is a success. An account/service-name database will be added in couchdb containing all informations needed for authentication and the konnector will be free to work on all endpoints within its scope.","title":"Couchdb"},{"location":"proxy/description/#why-we-need-a-proxy","text":"The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personnal clouds, following this guideline would mean that we need a client_id and a client_secret for each one of all the applications running. To answer this issue, two solutions are possible depending on what the energy supplier is willing to do. Providers could allow wildcard subdomains when registering the callback URI, it would parse the subdomain and adapt its redirection when answering /auth call. Example: https//*.cozygrandlyon.cloud/account/redirect -> parse subdomain before .cozy xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz toto.cozygrandlyon.cloud/account/redirect -> redirect to toto If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirections.","title":"Why we Need a Proxy"},{"location":"proxy/description/#result","text":"With that in mind, the proxy is now the one calling the auth and token provider endpoints. The instance name will be contained in redirect_uri, the stack will insert this parameters by itself in the /auth call. 3 endpoints are created in the proxy for each energy supplier : One for the auth One for the token One for the redirect uri","title":"Result"},{"location":"proxy/description/#proxy-flow","text":"","title":"Proxy flow"},{"location":"proxy/description/#proxy-code-explained","text":"reminder Feel free to check the proxy code at all time when reading this documentation. The proxy is coded in golang. It is composed of six endpoints as seen above. The first endpoint to be called is /auth .","title":"Proxy Code Explained"},{"location":"proxy/description/#auth","text":"Originally called from a cozy-stack trying to setup its konnector. The proxy gets these informations from the query: client_id duration redirect_uri (auto inserted by the cozy-stack, except if you specify skip_redirect_uri:true in the couchdb) response_type state (as it was conceived by the cozy-stack) The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling. With all these informations, the proxy can contact the provider /auth endpoint to start the oauth dance.","title":"auth"},{"location":"proxy/description/#enedis","text":"note See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the cozyOrigin instance name. This will be usefull when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer. Once the call is sent, enedis will point to the /redirect endpoint.","title":"Enedis"},{"location":"proxy/description/#grdf","text":"To be redacted","title":"Grdf"},{"location":"proxy/description/#redirect","text":"Retrieve the code , usage_point_id , and state answered by Enedis. Split the customed state that was modified in the /auth process. From this split it creates two variables : state host Finally redirect all these parameters in a query to the cozy-stack (the cozy-stack which is still waiting for an answer from its /auth call). state / instance The state must be recovered without the instance name, otherwise the cozy-stack won't recognized it and the handshake will fail.","title":"redirect"},{"location":"proxy/description/#token","text":"Gathering from query or parameters all params. Sends a post request to the provider /token endpoint. The stack will store the response params in a accounts couchdb database.","title":"token"},{"location":"proxy/monitoring/","text":"All logs printed by the Proxy are read and translated into statistics on a grafana dashboard. Grafana scaleway monitoring production address This monitoring system allow the team to parse more easily the cozy-stack logs when something goes wrong. For instance, test konnector or check from the proxy if an issue was coming from Enedis or Grdf. Learn more about how it works here . High volume The service parses a very high amount of logs, most of all when debugging an instance. To limit our disk usage we tend to stop the service when not needed. Just type docker-compose down to stop it in monitoring/logs-monitoring. The docker volume will be persisted. To easily plug loki on a specific instance: Click on configuration and data sources Add data sources Find Loki and type the loki url http://loki:3100 In the query builder select the container \"easy-cozy\" then add |= \"domain=[specific-instance]\"","title":"Monitoring"},{"location":"proxy/use_cases/enedis/","text":"Enedis Data Connect enedis documentation Create an account on https://datahub-enedis.fr/ to explore all the services exposed by Enedis. Authorize API swagger. Api healthcheck . Regarding Enedis, two endpoints are exposed: Authorize /dataconnect/v1/oauth2/authorize Parameter Description client_id Unique identifier of the Application response_type Authorization scenario requested. It will always be \"code\" as Enedis implemented a code grant authorization state Security parameter allowing to maintain the state between the request and the redirection. ** Maximum length of 100 characters ! ** duration Duration of the consent requested by the application, ISO 8601 format. It cannot exceed 3 years Important The response targets the redirect-uri registered with Enedis (the redirect-uri is our proxy and the response will be explained in details further below when explaining the proxy endpoints mechanics). Token /v1/oauth2/token Parameter Description redirect_uri URI defined when the application was created. Must be secured in https content-type application/json grant_type Authorization type to get an access token. This must be set to \u201cauthorization_code\u201d when using an authorization code, and to \u201crefresh_token\u201d when using a refresh token client_id Unique identifier of the Application client_secret Secret of the client application, associated with its client_id refresh_token Refresh token returned to the previous POST request to the /token endpoint code Authorization code returned to the GET request of /authorize endpoint On success, response will contain access_token or refresh_token , usage_point_id among other things. All informations will be stored by the cozy-stack in a cozy-accounts database. Consent Handling Consent is replaced everytime a new oauth dance is launched (for 6 months, hard coded in /authorize request). User can revoke its consent from the Enedis website, no external endpoints are available for this purpose. If a consent has been revoked or expired. A 403 error will be thrown saying: No consent can be found for this customer and this usage point . Ecolyo can warn the user that the service is unable to continue and ask to give new consent.","title":"Enedis"},{"location":"proxy/use_cases/enedis/#enedis-data-connect","text":"enedis documentation Create an account on https://datahub-enedis.fr/ to explore all the services exposed by Enedis. Authorize API swagger. Api healthcheck . Regarding Enedis, two endpoints are exposed:","title":"Enedis Data Connect"},{"location":"proxy/use_cases/enedis/#authorize","text":"","title":"Authorize"},{"location":"proxy/use_cases/enedis/#dataconnectv1oauth2authorize","text":"Parameter Description client_id Unique identifier of the Application response_type Authorization scenario requested. It will always be \"code\" as Enedis implemented a code grant authorization state Security parameter allowing to maintain the state between the request and the redirection. ** Maximum length of 100 characters ! ** duration Duration of the consent requested by the application, ISO 8601 format. It cannot exceed 3 years Important The response targets the redirect-uri registered with Enedis (the redirect-uri is our proxy and the response will be explained in details further below when explaining the proxy endpoints mechanics).","title":"/dataconnect/v1/oauth2/authorize"},{"location":"proxy/use_cases/enedis/#token","text":"","title":"Token"},{"location":"proxy/use_cases/enedis/#v1oauth2token","text":"Parameter Description redirect_uri URI defined when the application was created. Must be secured in https content-type application/json grant_type Authorization type to get an access token. This must be set to \u201cauthorization_code\u201d when using an authorization code, and to \u201crefresh_token\u201d when using a refresh token client_id Unique identifier of the Application client_secret Secret of the client application, associated with its client_id refresh_token Refresh token returned to the previous POST request to the /token endpoint code Authorization code returned to the GET request of /authorize endpoint On success, response will contain access_token or refresh_token , usage_point_id among other things. All informations will be stored by the cozy-stack in a cozy-accounts database.","title":"/v1/oauth2/token"},{"location":"proxy/use_cases/enedis/#consent-handling","text":"Consent is replaced everytime a new oauth dance is launched (for 6 months, hard coded in /authorize request). User can revoke its consent from the Enedis website, no external endpoints are available for this purpose. If a consent has been revoked or expired. A 403 error will be thrown saying: No consent can be found for this customer and this usage point . Ecolyo can warn the user that the service is unable to continue and ask to give new consent.","title":"Consent Handling"},{"location":"proxy/use_cases/grdfadict/","text":"Grdf Adict grdf documentation Visit https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict to explore all the services exposed by Grdf. Prod endpoints are: https://sofit-sso-oidc.grdf.fr/openam/ Regarding Grdf Adict Oauth connexion, two endpoints are exposed: Oauth connexion still in Beta Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a state parameter in the Oauth dance. Authorize /oauth2/realms/externeGrdf/authorize Token /oauth2/realms/externeGrdf/access_token The /access_token endpoint can be called with two different grant_type parameter. authorization_code gives an access token and will also retrieve the consents list given by the user in session. client_credentials gives only the access token allowing us to request the data service. The grdf Konnector would only need to call the client_credentials to get a refresh token. Consent Handling Consent is represented by an access right. This access holds characteristics specific to the consent of the end customer. Optional: Revoke consent from external applications It is possible to cancel a consent that was given from the user to our service (for test or development purpose for instance). api.grdf.fr/adict/v1/droit_acces/{id_accreditation}","title":"Grdf Adict"},{"location":"proxy/use_cases/grdfadict/#grdf-adict","text":"grdf documentation Visit https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict to explore all the services exposed by Grdf. Prod endpoints are: https://sofit-sso-oidc.grdf.fr/openam/ Regarding Grdf Adict Oauth connexion, two endpoints are exposed: Oauth connexion still in Beta Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a state parameter in the Oauth dance.","title":"Grdf Adict"},{"location":"proxy/use_cases/grdfadict/#authorize","text":"","title":"Authorize"},{"location":"proxy/use_cases/grdfadict/#oauth2realmsexternegrdfauthorize","text":"","title":"/oauth2/realms/externeGrdf/authorize"},{"location":"proxy/use_cases/grdfadict/#token","text":"","title":"Token"},{"location":"proxy/use_cases/grdfadict/#oauth2realmsexternegrdfaccess_token","text":"The /access_token endpoint can be called with two different grant_type parameter. authorization_code gives an access token and will also retrieve the consents list given by the user in session. client_credentials gives only the access token allowing us to request the data service. The grdf Konnector would only need to call the client_credentials to get a refresh token.","title":"/oauth2/realms/externeGrdf/access_token"},{"location":"proxy/use_cases/grdfadict/#consent-handling","text":"Consent is represented by an access right. This access holds characteristics specific to the consent of the end customer.","title":"Consent Handling"},{"location":"proxy/use_cases/grdfadict/#optional-revoke-consent-from-external-applications","text":"It is possible to cancel a consent that was given from the user to our service (for test or development purpose for instance). api.grdf.fr/adict/v1/droit_acces/{id_accreditation}","title":"Optional: Revoke consent from external applications"}]}
\ No newline at end of file
+{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"This documentation covers the technical aspects of projects developed by the Grandlyon in cooperation with Cozy Cloud . Installing prerequisites In order to work with a self-data environment, there are a couple of prerequisites. Don't forget to take a look at our general development guidelines wiki first. Name Required Details Node Yes Node 16 must be installed as it is the version that runs on the official cozystack. Yarn Yes Yarn is our projects package manager. Docker Yes See cozystack for more information. Docker-compose Yes WSL No Required for windows users. Usage Node NVM You might need to manage several NodeJS versions on the same computer when working on different projects. To manage it properly, you can use the nvm package on windows or n package on linux. $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version $ nvm install X.X.X $ nvm list $ nvm use X.X.X $ node -v WSL First open Powershell as administrator and launch the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot . Upgrade to WSL 2 If you're on WSL 1 and want to upgrade to WSL 2, here is the process: Open an elevated powershell and paste the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart Then, enable the Virtual Machine Platform optional feature. dism . exe / online / enable-feature / featurename : VirtualMachinePlatform / all / norestart Now restart your computer to apply these features. Once it's done, open an elevated powershell again and set the default wsl version to 2 $ wsl --set-default-version 2 You might see this message after running the command above WSL 2 requires an update to its kernel component. For information please visit wsl2kernel . If you install the MSI from wsl2kernel . Once you have the kernel installed, please run wsl --set-default-version 2 again and it should complete successfully without showing the message. Install your Linux distribution After reboot, open the microsoft store and install the distribution of your choice, for instance: Ubuntu 20.04 lts . Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list. Setup your distribution Start updating the packages list by typing: $ sudo apt update Install nodejs using the apt package manager $ sudo apt install To verify the Installation execute the following command: $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: $ sudo apt install npm To verify the npm Install check using the command: $ npm --version To Download and Setup Yarn $ sudo apt install yarn To check the installed version of Yarn: $ yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands: sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on. Contributing to the documentation To install and run the documentation on your laptop, follow the steps in the README . Then: Create a branch for your change Add documentation pages to docs , and supporting assets to img . Write some markdown Submit a merge request","title":"Getting started"},{"location":"#_1","text":"This documentation covers the technical aspects of projects developed by the Grandlyon in cooperation with Cozy Cloud .","title":""},{"location":"#installing-prerequisites","text":"In order to work with a self-data environment, there are a couple of prerequisites. Don't forget to take a look at our general development guidelines wiki first. Name Required Details Node Yes Node 16 must be installed as it is the version that runs on the official cozystack. Yarn Yes Yarn is our projects package manager. Docker Yes See cozystack for more information. Docker-compose Yes WSL No Required for windows users.","title":"Installing prerequisites"},{"location":"#usage","text":"","title":"Usage"},{"location":"#node-nvm","text":"You might need to manage several NodeJS versions on the same computer when working on different projects. To manage it properly, you can use the nvm package on windows or n package on linux. $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version $ nvm install X.X.X $ nvm list $ nvm use X.X.X $ node -v","title":"Node NVM"},{"location":"#wsl","text":"First open Powershell as administrator and launch the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot .","title":"WSL"},{"location":"#upgrade-to-wsl-2","text":"If you're on WSL 1 and want to upgrade to WSL 2, here is the process: Open an elevated powershell and paste the following command: dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart Then, enable the Virtual Machine Platform optional feature. dism . exe / online / enable-feature / featurename : VirtualMachinePlatform / all / norestart Now restart your computer to apply these features. Once it's done, open an elevated powershell again and set the default wsl version to 2 $ wsl --set-default-version 2 You might see this message after running the command above WSL 2 requires an update to its kernel component. For information please visit wsl2kernel . If you install the MSI from wsl2kernel . Once you have the kernel installed, please run wsl --set-default-version 2 again and it should complete successfully without showing the message.","title":"Upgrade to WSL 2"},{"location":"#install-your-linux-distribution","text":"After reboot, open the microsoft store and install the distribution of your choice, for instance: Ubuntu 20.04 lts . Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list.","title":"Install your Linux distribution"},{"location":"#setup-your-distribution","text":"Start updating the packages list by typing: $ sudo apt update Install nodejs using the apt package manager $ sudo apt install To verify the Installation execute the following command: $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: $ sudo apt install npm To verify the npm Install check using the command: $ npm --version To Download and Setup Yarn $ sudo apt install yarn To check the installed version of Yarn: $ yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands: sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on.","title":"Setup your distribution"},{"location":"#contributing-to-the-documentation","text":"To install and run the documentation on your laptop, follow the steps in the README . Then: Create a branch for your change Add documentation pages to docs , and supporting assets to img . Write some markdown Submit a merge request","title":"Contributing to the documentation"},{"location":"external_doc/","text":"Grandlyon ressources Link Details WIKI This wiki covers all the processes and guidelines towards developers. Cozy ressources Link Details COZY Full technical documentation for all cozy libs. MATTERMOST Chat app for exange between G.Lyon & Cozy.","title":"Additional Ressources"},{"location":"external_doc/#grandlyon-ressources","text":"Link Details WIKI This wiki covers all the processes and guidelines towards developers.","title":"Grandlyon ressources"},{"location":"external_doc/#cozy-ressources","text":"Link Details COZY Full technical documentation for all cozy libs. MATTERMOST Chat app for exange between G.Lyon & Cozy.","title":"Cozy ressources"},{"location":"easycozy/","text":"What is easy-cozy Why we use easy-cozy How we use it","title":"Introduction"},{"location":"easycozy/#what-is-easy-cozy","text":"","title":"What is easy-cozy"},{"location":"easycozy/#why-we-use-easy-cozy","text":"","title":"Why we use easy-cozy"},{"location":"easycozy/#how-we-use-it","text":"","title":"How we use it"},{"location":"easycozy/commands/","text":"Commands This section includes all common commands used on dev environment. App Install a specific version of an app $ cd /easy-cozy $ docker-compose exec cozy ./cozy apps update home --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://github.com/doubleface/cozy-collect.git#build-debug Konnector Install a specific version of a konnector $ cd /easy-cozy # cozy-stack konnectors uninstall ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors uninstall grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been uninstalled # cozy-stack konnectors install ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors install grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://forge.grandlyon.com/web-et-numerique/llle_project/grdf-adict-konnector.git#build grdfgrandlyon ( 0 .1.5-a3f6f05d9fde7c705b811658b3ce3667a9d7d0b5 ) has been installed on [ name ] .cozy.self-data.alpha.grandlyon.com Update the version of a konnector $ cd /easy-cozy # cozy-stack konnectors update ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors update grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been upgraded to 0 .1.5-d4bbe7350ecf13d13734f559c538e3c0ee8dc7ae Run a konnector from the stack $ cd /root/easy-cozy # cozy-stack konnectors run ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors run grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" Instance Set log level to debug for an instance $ cd /root/easy-cozy # cozy-stack instances debug ${url} true $ docker-compose exec cozy ./cozy instances debug --domain \"[name].cozy.self-data.alpha.grandlyon.com\" true List all instances $ cd /root/easy-cozy # cozy-stack instances ls $ docker-compose exec cozy ./cozy instances ls Stack Check stack version $ cd /easy-cozy $ docker-compose exec cozy ./cozy version Update stack version Update version in the Dockerfile on gitlab. On server : git pull or change locally the version in cozy-stack/Dockerfile create the docker image using: cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image cd .. docker-compose up -d cozy Error encounter Docker container was not launched, when consulting logs we can see the following error ./cozy: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./cozy) We have replaced debian:stable-slim with ubuntu:20.10 as installer for our docker build: https://forge.grandlyon.com/pocs/cozy/easy-cozy/-/commit/48a30a03f209169e0f1ebb0d106bb4361e7cd167","title":"Commands"},{"location":"easycozy/commands/#commands","text":"This section includes all common commands used on dev environment.","title":"Commands"},{"location":"easycozy/commands/#app","text":"","title":"App"},{"location":"easycozy/commands/#install-a-specific-version-of-an-app","text":"$ cd /easy-cozy $ docker-compose exec cozy ./cozy apps update home --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://github.com/doubleface/cozy-collect.git#build-debug","title":"Install a specific version of an app"},{"location":"easycozy/commands/#konnector","text":"","title":"Konnector"},{"location":"easycozy/commands/#install-a-specific-version-of-a-konnector","text":"$ cd /easy-cozy # cozy-stack konnectors uninstall ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors uninstall grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been uninstalled # cozy-stack konnectors install ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors install grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" git://forge.grandlyon.com/web-et-numerique/llle_project/grdf-adict-konnector.git#build grdfgrandlyon ( 0 .1.5-a3f6f05d9fde7c705b811658b3ce3667a9d7d0b5 ) has been installed on [ name ] .cozy.self-data.alpha.grandlyon.com","title":"Install a specific version of a konnector"},{"location":"easycozy/commands/#update-the-version-of-a-konnector","text":"$ cd /easy-cozy # cozy-stack konnectors update ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors update grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been upgraded to 0 .1.5-d4bbe7350ecf13d13734f559c538e3c0ee8dc7ae","title":"Update the version of a konnector"},{"location":"easycozy/commands/#run-a-konnector-from-the-stack","text":"$ cd /root/easy-cozy # cozy-stack konnectors run ${konn} --domain ${url} $ docker-compose exec cozy ./cozy konnectors run grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\"","title":"Run a konnector from the stack"},{"location":"easycozy/commands/#instance","text":"","title":"Instance"},{"location":"easycozy/commands/#set-log-level-to-debug-for-an-instance","text":"$ cd /root/easy-cozy # cozy-stack instances debug ${url} true $ docker-compose exec cozy ./cozy instances debug --domain \"[name].cozy.self-data.alpha.grandlyon.com\" true","title":"Set log level to debug for an instance"},{"location":"easycozy/commands/#list-all-instances","text":"$ cd /root/easy-cozy # cozy-stack instances ls $ docker-compose exec cozy ./cozy instances ls","title":"List all instances"},{"location":"easycozy/commands/#stack","text":"","title":"Stack"},{"location":"easycozy/commands/#check-stack-version","text":"$ cd /easy-cozy $ docker-compose exec cozy ./cozy version","title":"Check stack version"},{"location":"easycozy/commands/#update-stack-version","text":"Update version in the Dockerfile on gitlab. On server : git pull or change locally the version in cozy-stack/Dockerfile create the docker image using: cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image cd .. docker-compose up -d cozy Error encounter Docker container was not launched, when consulting logs we can see the following error ./cozy: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./cozy) We have replaced debian:stable-slim with ubuntu:20.10 as installer for our docker build: https://forge.grandlyon.com/pocs/cozy/easy-cozy/-/commit/48a30a03f209169e0f1ebb0d106bb4361e7cd167","title":"Update stack version"},{"location":"easycozy/config/","text":"Configuration This section includes all configurations available for the stack. Configuration File The stack's configuration file is located at .easy-cozy/cozystack/cozy.yml . It can be edited in order to changes various parameters, smtp, logs ... SMTP Modify the cozy.yml responsible for the configuration : mail : # mail noreply address - flags: --mail-noreply-address noreply_address : noreply @localhost noreply_name : My Cozy reply_to : support @cozycloud . cc # mail smtp host - flags: --mail-host host : smtp . home # mail smtp port - flags: --mail-port port : 465 # mail smtp username - flags: --mail-username username : {{ . Env . COZY_MAIL_USERNAME }} # mail smtp password - flags: --mail-password password : {{ . Env . COZY_MAIL_PASSWORD }} # disable mail tls - flags: --mail-disable-tls disable_tls : false # skip the certificate validation (may be useful on localhost) skip_certificate_validation : false known issue A known cozy-stack issue here causes you to have to change the above configuration with: mail: # mail smtp port - flags: --mail-port port: 587 # disable mail tls - flags: --mail-disable-tls disable_tls: true After updating configuration don't forget to restart your cozy-stack : docker-compose restart cozy","title":"Configuration"},{"location":"easycozy/config/#configuration","text":"This section includes all configurations available for the stack.","title":"Configuration"},{"location":"easycozy/config/#configuration-file","text":"The stack's configuration file is located at .easy-cozy/cozystack/cozy.yml . It can be edited in order to changes various parameters, smtp, logs ...","title":"Configuration File"},{"location":"easycozy/config/#smtp","text":"Modify the cozy.yml responsible for the configuration : mail : # mail noreply address - flags: --mail-noreply-address noreply_address : noreply @localhost noreply_name : My Cozy reply_to : support @cozycloud . cc # mail smtp host - flags: --mail-host host : smtp . home # mail smtp port - flags: --mail-port port : 465 # mail smtp username - flags: --mail-username username : {{ . Env . COZY_MAIL_USERNAME }} # mail smtp password - flags: --mail-password password : {{ . Env . COZY_MAIL_PASSWORD }} # disable mail tls - flags: --mail-disable-tls disable_tls : false # skip the certificate validation (may be useful on localhost) skip_certificate_validation : false known issue A known cozy-stack issue here causes you to have to change the above configuration with: mail: # mail smtp port - flags: --mail-port port: 587 # disable mail tls - flags: --mail-disable-tls disable_tls: true After updating configuration don't forget to restart your cozy-stack : docker-compose restart cozy","title":"SMTP"},{"location":"easycozy/known_errors/","text":"Oops... Sometime the stack get stuck when we reset several instances, overflowing our message broker rabbitmq. The following screen is then obtained when trying to access an instance: On the server, we can see that the server is underwater by using \"top\" command: To fix this issue, just restart the service on the server with \"docker-compose down / docker-compose up -d\" in the easy-cozy folder:","title":"Known errors"},{"location":"easycozy/known_errors/#oops","text":"Sometime the stack get stuck when we reset several instances, overflowing our message broker rabbitmq. The following screen is then obtained when trying to access an instance: On the server, we can see that the server is underwater by using \"top\" command: To fix this issue, just restart the service on the server with \"docker-compose down / docker-compose up -d\" in the easy-cozy folder:","title":"Oops..."},{"location":"easycozy/scripts/","text":"Scripts Easy cozy project comes with 2 main scripts: create-instance.sh: used to create an instance for a user remove-instance.sh: used to remove an instance for a specific user In addition of these scripts we have added custom scripts for some specific needs. All these scripts are available in the \"ecolyo-infra-scripts/admin_scripts\" folder Scripts for instances Scripts Args Description reset_instance.sh instance_username Remove and recreate again the instance for a given user Scripts for applications Scripts Args Description update_all_ecolyo_dev.sh none update Ecolyo with last version from build-dev branch on all instances update_ecolyo_master.sh instance_username update Ecolyo with last version from build branch on a specific instance update_ecolyo_dev.sh instance_username update Ecolyo with last version from build-dev branch on a specific instance update_ecolyo_test.sh instance_username update Ecolyo with last version from build-test branch on a specific instance update_pilote_master.sh instance_username update Pilote with last version from build-dev branch on a specific instance update_pilote_dev.sh instance_username update Pilote with last version from build-test branch on a specific instance Scripts for konnectors Scripts Args Description update_enedis_konnector_prod.sh instance_username update Enedis konnector with last version from build branch on a specific instance update_enedis_konnector_dev.sh instance_username update Enedis konnector with last version from build-dev branch on a specific instance","title":"Scripts"},{"location":"easycozy/scripts/#scripts","text":"Easy cozy project comes with 2 main scripts: create-instance.sh: used to create an instance for a user remove-instance.sh: used to remove an instance for a specific user In addition of these scripts we have added custom scripts for some specific needs. All these scripts are available in the \"ecolyo-infra-scripts/admin_scripts\" folder","title":"Scripts"},{"location":"easycozy/scripts/#scripts-for-instances","text":"Scripts Args Description reset_instance.sh instance_username Remove and recreate again the instance for a given user","title":"Scripts for instances"},{"location":"easycozy/scripts/#scripts-for-applications","text":"Scripts Args Description update_all_ecolyo_dev.sh none update Ecolyo with last version from build-dev branch on all instances update_ecolyo_master.sh instance_username update Ecolyo with last version from build branch on a specific instance update_ecolyo_dev.sh instance_username update Ecolyo with last version from build-dev branch on a specific instance update_ecolyo_test.sh instance_username update Ecolyo with last version from build-test branch on a specific instance update_pilote_master.sh instance_username update Pilote with last version from build-dev branch on a specific instance update_pilote_dev.sh instance_username update Pilote with last version from build-test branch on a specific instance","title":"Scripts for applications"},{"location":"easycozy/scripts/#scripts-for-konnectors","text":"Scripts Args Description update_enedis_konnector_prod.sh instance_username update Enedis konnector with last version from build branch on a specific instance update_enedis_konnector_dev.sh instance_username update Enedis konnector with last version from build-dev branch on a specific instance","title":"Scripts for konnectors"},{"location":"easycozy/tips/","text":"Tips Query data from an instance For maintenance reason, we sometime need to check data on a specific instance. For that we use postman to send get / post / delete data. All possibility are described in the data section of Cozy documentation . Example The example will describe how to query userChallenge data from \"ecolyotest\" instance. First, you need to be able to connect to the instance in order to retrieve the bearer and the cozysessid. Then use postman to query the data: Verb: GET Request: https://ecolyotest.cozy.self-data.alpha.grandlyon.com/data/com.grandlyon.ecolyo.userchallenge/_all_docs?include_docs=true Header: Accept: application/json content-type: application/json Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Cookie: cozysessid=AAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx The result will then be retrieve by postman: { \"total_rows\": 1, \"offset\": 0, \"rows\": [ { \"id\": \"a353b985c0c5f09229b0acd6b2f37f1b\", \"key\": \"a353b985c0c5f09229b0acd6b2f37f1b\", ... ] } Delete a doctype from a instance You can use ACH to delete a doctype. Please find the ACH documentation to see all commands Example The example will describe how to drop userChallenge doctype from \"ecolyotest\" instance. the token provided is the one present in the cozysessid. $ ach -t xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -u https://ecolyotest.cozy.self-data.alpha.grandlyon.com drop com.grandlyon.ecolyo.userchallenge This doctypes will be removed. * com.grandlyon.ecolyo.userchallenge Type \"yes\" if ok. yes A browser window will be opened asking for authorization to access to your file. Just click on \"Authorize\" to keep on with the doctype dropping.","title":"Tips"},{"location":"easycozy/tips/#tips","text":"","title":"Tips"},{"location":"easycozy/tips/#query-data-from-an-instance","text":"For maintenance reason, we sometime need to check data on a specific instance. For that we use postman to send get / post / delete data. All possibility are described in the data section of Cozy documentation . Example The example will describe how to query userChallenge data from \"ecolyotest\" instance. First, you need to be able to connect to the instance in order to retrieve the bearer and the cozysessid. Then use postman to query the data: Verb: GET Request: https://ecolyotest.cozy.self-data.alpha.grandlyon.com/data/com.grandlyon.ecolyo.userchallenge/_all_docs?include_docs=true Header: Accept: application/json content-type: application/json Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Cookie: cozysessid=AAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx The result will then be retrieve by postman: { \"total_rows\": 1, \"offset\": 0, \"rows\": [ { \"id\": \"a353b985c0c5f09229b0acd6b2f37f1b\", \"key\": \"a353b985c0c5f09229b0acd6b2f37f1b\", ... ] }","title":"Query data from an instance"},{"location":"easycozy/tips/#delete-a-doctype-from-a-instance","text":"You can use ACH to delete a doctype. Please find the ACH documentation to see all commands Example The example will describe how to drop userChallenge doctype from \"ecolyotest\" instance. the token provided is the one present in the cozysessid. $ ach -t xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -u https://ecolyotest.cozy.self-data.alpha.grandlyon.com drop com.grandlyon.ecolyo.userchallenge This doctypes will be removed. * com.grandlyon.ecolyo.userchallenge Type \"yes\" if ok. yes A browser window will be opened asking for authorization to access to your file. Just click on \"Authorize\" to keep on with the doctype dropping.","title":"Delete a doctype from a instance"},{"location":"ecolyo/","text":"Ecolyo is a multi-fluid application solution towards users of the grand lyon metropolis to monitor and optimize their energy consumption. Reminder If you're a new developer tasked to work on this project, please get acquainted with the team processes and read the advised dev environment documentation and the self-data prerequisites . Repositories ecolyo ecolyo-agent server ecolyo-agent client","title":"Introduction"},{"location":"ecolyo/#repositories","text":"ecolyo ecolyo-agent server ecolyo-agent client","title":"Repositories"},{"location":"ecolyo/application/deploy/","text":"Deploy This section will show you how to deploy your project on different environments. Deploy build to builds branches 3 builds branch are today available for Ecolyo: build : reflect the build of the master branch and the version deployed in production environment build-dev : reflect the build of the dev branch and the version deployed on dev environment build-test : reflect a temporary build which can be used for test purpose Windows users Some command did not run on Windows. Please use your Linux distribution installed on your WSL. For more information about it see the Install WSL section Make sure that: you are on the right branch (dev or master) depending on the enviroment you need to deploy. your branch is up to date you node modules are up to date First build the application : $ yarn build Next you can deploy the build to the target branch: # deploy on build-test branch $ yarn deploy-test # deploy on build-dev branch $ yarn deploy-dev # deploy on build branch $ yarn deploy Auto deploy for dev In order to prevent manual action for deployment, a gitlab-runner has been configured to deploy every changes on the dev branch on our test env cicd scripts You can find all scripts used in cicd jobs on the following repository Deploy build-test branch to one Scaleway instance for testing You can directly use the content of build-test branch to update one instance for test purpose. Simply use the dedicated script \"update_ecolyo_test.sh \" with the targeted instance (from the server). By default we use the ecolyotest instance for testing intermediate functionnality. For more information you can check for Easy Cozy scripts . Deploy build-dev branch to all Scaleway instances You can directly use the content of build-dev branch to update apps on dev environment using scripts (from the server). Simply use the dedicated script \"update_all_ecolyo_dev.sh\" (from the server). For more information you can check for Easy Cozy scripts . Deploy build branch to Cozy You can deploy content of build branch into Cozy registry by using the cozy-app-publish command after replacing following value: $REGISTRY_TOKEN : token provided by Cozy team $VERSION_NUMBER: version of the application $COZY_SPACE: space of the Cozy $ yarn cozy-app-publish --token $REGISTRY_TOKEN --build-url https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/-/archive/build/ecolyo-build.tar.gz --manual-version $VERSION_NUMBER --space $COZY_SPACE More information at cozy-app-publish/","title":"Deploy"},{"location":"ecolyo/application/deploy/#deploy","text":"This section will show you how to deploy your project on different environments.","title":"Deploy"},{"location":"ecolyo/application/deploy/#deploy-build-to-builds-branches","text":"3 builds branch are today available for Ecolyo: build : reflect the build of the master branch and the version deployed in production environment build-dev : reflect the build of the dev branch and the version deployed on dev environment build-test : reflect a temporary build which can be used for test purpose Windows users Some command did not run on Windows. Please use your Linux distribution installed on your WSL. For more information about it see the Install WSL section Make sure that: you are on the right branch (dev or master) depending on the enviroment you need to deploy. your branch is up to date you node modules are up to date First build the application : $ yarn build Next you can deploy the build to the target branch: # deploy on build-test branch $ yarn deploy-test # deploy on build-dev branch $ yarn deploy-dev # deploy on build branch $ yarn deploy","title":"Deploy build to builds branches"},{"location":"ecolyo/application/deploy/#auto-deploy-for-dev","text":"In order to prevent manual action for deployment, a gitlab-runner has been configured to deploy every changes on the dev branch on our test env cicd scripts You can find all scripts used in cicd jobs on the following repository","title":"Auto deploy for dev"},{"location":"ecolyo/application/deploy/#deploy-build-test-branch-to-one-scaleway-instance-for-testing","text":"You can directly use the content of build-test branch to update one instance for test purpose. Simply use the dedicated script \"update_ecolyo_test.sh \" with the targeted instance (from the server). By default we use the ecolyotest instance for testing intermediate functionnality. For more information you can check for Easy Cozy scripts .","title":"Deploy build-test branch to one Scaleway instance for testing"},{"location":"ecolyo/application/deploy/#deploy-build-dev-branch-to-all-scaleway-instances","text":"You can directly use the content of build-dev branch to update apps on dev environment using scripts (from the server). Simply use the dedicated script \"update_all_ecolyo_dev.sh\" (from the server). For more information you can check for Easy Cozy scripts .","title":"Deploy build-dev branch to all Scaleway instances"},{"location":"ecolyo/application/deploy/#deploy-build-branch-to-cozy","text":"You can deploy content of build branch into Cozy registry by using the cozy-app-publish command after replacing following value: $REGISTRY_TOKEN : token provided by Cozy team $VERSION_NUMBER: version of the application $COZY_SPACE: space of the Cozy $ yarn cozy-app-publish --token $REGISTRY_TOKEN --build-url https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/-/archive/build/ecolyo-build.tar.gz --manual-version $VERSION_NUMBER --space $COZY_SPACE More information at cozy-app-publish/","title":"Deploy build branch to Cozy"},{"location":"ecolyo/application/description/","text":"Ecolyo is a Cozy application that allows users to connect their energy accounts such as EGL , ENEDIS and GRDF , using cozy konnectors","title":"Description"},{"location":"ecolyo/application/gitflow/","text":"Initialize Create a new project in gitlab and take note of its url Protecting Master Branch On the gitlab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be using merge requests. Setting Development Branch Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/web-et-numerique/llle.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev Start Developing For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch Conventional Commits The commit contains the following structural types : fix feature In our team organisation we are using IceScrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a feature branch name should follow this structure: features/<number of the User Story>-<title_of_the_user_story> You can create the branch by typing: git checkout -b features/<number of the User Story>-<title_of_the_user_story> Note that the feature type is the only one with a dedicated folder (features/-US). Each fix branch should be named as the following fix-\\<title_of_the_fix> . You can create the branch by typing: git checkout -b fix-<title_of_the_fix> Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. Types other than fix and feature are allowed, for example build , chore , ci , docs , style , refactor , perf , test and others. add tag git tag -a 1.0.0 -m \"complementary message\" Gitflow Scheme","title":"Gitflow"},{"location":"ecolyo/application/gitflow/#initialize","text":"Create a new project in gitlab and take note of its url","title":"Initialize"},{"location":"ecolyo/application/gitflow/#protecting-master-branch","text":"On the gitlab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be using merge requests.","title":"Protecting Master Branch"},{"location":"ecolyo/application/gitflow/#setting-development-branch","text":"Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/web-et-numerique/llle.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev","title":"Setting Development Branch"},{"location":"ecolyo/application/gitflow/#start-developing","text":"For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch","title":"Start Developing"},{"location":"ecolyo/application/gitflow/#conventional-commits","text":"The commit contains the following structural types : fix feature In our team organisation we are using IceScrum to keep track of our User Stories (US). Each US is identified by a number. In order to easily identify the commit that refers to the US, a feature branch name should follow this structure: features/<number of the User Story>-<title_of_the_user_story> You can create the branch by typing: git checkout -b features/<number of the User Story>-<title_of_the_user_story> Note that the feature type is the only one with a dedicated folder (features/-US). Each fix branch should be named as the following fix-\\<title_of_the_fix> . You can create the branch by typing: git checkout -b fix-<title_of_the_fix> Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. Types other than fix and feature are allowed, for example build , chore , ci , docs , style , refactor , perf , test and others. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Conventional Commits"},{"location":"ecolyo/application/gitflow/#gitflow-scheme","text":"","title":"Gitflow Scheme"},{"location":"ecolyo/application/mail/","text":"Explenation A templating system was needed for the app. In order to make it easy to use and also responsive, two libs has been used : - Handelbars - MJML Handlebars is used as a semantic template motor. It allow us to split email template in order to reuse some parts (header, footer ...) Mjml is a lib providing a syntax allowing developers to easly build responsive templates. Usage Scaffolding Mails templates can be found inside src/notifications . All reusable parts can be found in base folder. All stylesheet must be include inside style.hbs . Create your template Simply create your template file : template.hbs inside the notifications folder. <mj-hero background-color=\"radial-gradient(96.2% 96.2% at 50% 3.8%, #343641 0%, #1B1C22 100%)\" padding=\"17px\"> <mj-text align=\"center\" color=\"white\" padding-top=\"20px\" font-size=\"24px\" font-family=\"Lato\" font-weight=\"normal\"> <img style=\"vertical-align: middle; margin-right: 12px\" src=\"https://ecolyo.com/assets/ecolyo-icon.svg\" alt=\"Ecolyo\"/> {{title}} </mj-text> </mj-hero> How to use it ? Inside a cozy service 1) Import the mjml lib in order to compile the template. import mjml2html from 'mjml' 2) Link all the info mandatory to render your email : const template = monthlyReportTemplate({ title: 'Du nouveau dans votre espace Ecolyo !', }) 3) Build the email and send it: const mailData = { mode: 'noreply', subject: '[Ecolyo] - Votre bilan mensuel', parts: [ { type: 'text/html', body: mjml2html(template).html, }, ], } mailService.SendMail(client, mailData) Inside the app It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why wy need to change the import for mjml lib into : const mjml2html = require('mjml-browser') Useful links Mjml live editor","title":"Mail"},{"location":"ecolyo/application/mail/#explenation","text":"A templating system was needed for the app. In order to make it easy to use and also responsive, two libs has been used : - Handelbars - MJML Handlebars is used as a semantic template motor. It allow us to split email template in order to reuse some parts (header, footer ...) Mjml is a lib providing a syntax allowing developers to easly build responsive templates.","title":"Explenation"},{"location":"ecolyo/application/mail/#usage","text":"","title":"Usage"},{"location":"ecolyo/application/mail/#scaffolding","text":"Mails templates can be found inside src/notifications . All reusable parts can be found in base folder. All stylesheet must be include inside style.hbs .","title":"Scaffolding"},{"location":"ecolyo/application/mail/#create-your-template","text":"Simply create your template file : template.hbs inside the notifications folder. <mj-hero background-color=\"radial-gradient(96.2% 96.2% at 50% 3.8%, #343641 0%, #1B1C22 100%)\" padding=\"17px\"> <mj-text align=\"center\" color=\"white\" padding-top=\"20px\" font-size=\"24px\" font-family=\"Lato\" font-weight=\"normal\"> <img style=\"vertical-align: middle; margin-right: 12px\" src=\"https://ecolyo.com/assets/ecolyo-icon.svg\" alt=\"Ecolyo\"/> {{title}} </mj-text> </mj-hero>","title":"Create your template"},{"location":"ecolyo/application/mail/#how-to-use-it","text":"","title":"How to use it ?"},{"location":"ecolyo/application/mail/#inside-a-cozy-service","text":"1) Import the mjml lib in order to compile the template. import mjml2html from 'mjml' 2) Link all the info mandatory to render your email : const template = monthlyReportTemplate({ title: 'Du nouveau dans votre espace Ecolyo !', }) 3) Build the email and send it: const mailData = { mode: 'noreply', subject: '[Ecolyo] - Votre bilan mensuel', parts: [ { type: 'text/html', body: mjml2html(template).html, }, ], } mailService.SendMail(client, mailData)","title":"Inside a cozy service"},{"location":"ecolyo/application/mail/#inside-the-app","text":"It's very similar to service usage, but because we use react, the app rendering is done in the user browser. That's why wy need to change the import for mjml lib into : const mjml2html = require('mjml-browser')","title":"Inside the app"},{"location":"ecolyo/application/mail/#useful-links","text":"Mjml live editor","title":"Useful links"},{"location":"ecolyo/application/redux/","text":"Redux There are two main store created for this app: Cozy: store information about cozy (konnectors, accounts, settings, db) Ecolyo: store all states used for this app For a better state management, combineReducers(reducers) is used to split the reducing function into seperate functions. So, each managing independent parts of the state. Ecolyo Store Structure Reducer Type Description global GlobalState store global states such as: notification, type device or fluid type GlobalState enum - screenType = ScreenType - challengeExplorationNotification = boolean releaseNotes = ReleaseNotes termsStatus = TermsStatus openPartnersIssueModal = boolean - challengeActionNotification = boolean - challengeDuelNotification = boolean - analysisNotification = boolean - fluidStatus = FluidStatus[] - fluidTypes = FluidType[] profile Profile store states about profile information such as: notification, connectionDate profileType ProfileTypeState store states about user's profileType filled through the profile form profileEcogesture ProfileEcogestureState store states about user's profileEcogesture filled through the profile ecogesture form chart ChartState store consumption chart states such as: timeStep, graph data ChartState enum - selectedDate = DateTime - currentTimeStep = TimeStep - currentIndex = number - currentDatachart = Datachart - currentDatachartIndex = number - loading = boolean modal ModalState store opening state of the feedback modal ModalState enum - isFeedbacksOpen = boolean challenge ChallengeState store challenge state such as: list of user challenge, data load and current challenge ChallengeState enum - userChallengeList = UserChallenge[] - currentChallenge = UserChallenge - currentDataload = Dataload[] Updating state process Redux-thunk middleware is configured. For now, it is used only for updating the profile. To update a state, a webservice method is called before trigger a state change inside the store.","title":"Redux"},{"location":"ecolyo/application/redux/#redux","text":"There are two main store created for this app: Cozy: store information about cozy (konnectors, accounts, settings, db) Ecolyo: store all states used for this app For a better state management, combineReducers(reducers) is used to split the reducing function into seperate functions. So, each managing independent parts of the state.","title":"Redux"},{"location":"ecolyo/application/redux/#ecolyo-store-structure","text":"Reducer Type Description global GlobalState store global states such as: notification, type device or fluid type GlobalState enum - screenType = ScreenType - challengeExplorationNotification = boolean releaseNotes = ReleaseNotes termsStatus = TermsStatus openPartnersIssueModal = boolean - challengeActionNotification = boolean - challengeDuelNotification = boolean - analysisNotification = boolean - fluidStatus = FluidStatus[] - fluidTypes = FluidType[] profile Profile store states about profile information such as: notification, connectionDate profileType ProfileTypeState store states about user's profileType filled through the profile form profileEcogesture ProfileEcogestureState store states about user's profileEcogesture filled through the profile ecogesture form chart ChartState store consumption chart states such as: timeStep, graph data ChartState enum - selectedDate = DateTime - currentTimeStep = TimeStep - currentIndex = number - currentDatachart = Datachart - currentDatachartIndex = number - loading = boolean modal ModalState store opening state of the feedback modal ModalState enum - isFeedbacksOpen = boolean challenge ChallengeState store challenge state such as: list of user challenge, data load and current challenge ChallengeState enum - userChallengeList = UserChallenge[] - currentChallenge = UserChallenge - currentDataload = Dataload[]","title":"Ecolyo Store Structure"},{"location":"ecolyo/application/redux/#updating-state-process","text":"Redux-thunk middleware is configured. For now, it is used only for updating the profile. To update a state, a webservice method is called before trigger a state change inside the store.","title":"Updating state process"},{"location":"ecolyo/application/release/","text":"Release This section will show you how to properly create a release for the app. Conventionnal commit The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. The commit message should be structured as follows: <type>[optional scope]: <description> [optional body] [optional footer(s)] The commit contains the following structural elements, to communicate intent to the consumers of your library: fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning). feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning). BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type. types other than fix: and feat: are allowed, for example @commitlint/config-conventional (based on the the Angular convention) recommends build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others. footers other than BREAKING CHANGE: may be provided and follow a convention similar to git trailer format. standard-version Standard-version is librairie javascript that allow to handle easly tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and upadte changelog file. yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0) Useful links Conventional commit doc Lib link","title":"Release"},{"location":"ecolyo/application/release/#release","text":"This section will show you how to properly create a release for the app.","title":"Release"},{"location":"ecolyo/application/release/#conventionnal-commit","text":"The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages. The commit message should be structured as follows: <type>[optional scope]: <description> [optional body] [optional footer(s)] The commit contains the following structural elements, to communicate intent to the consumers of your library: fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning). feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning). BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type. types other than fix: and feat: are allowed, for example @commitlint/config-conventional (based on the the Angular convention) recommends build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others. footers other than BREAKING CHANGE: may be provided and follow a convention similar to git trailer format.","title":"Conventionnal commit"},{"location":"ecolyo/application/release/#standard-version","text":"Standard-version is librairie javascript that allow to handle easly tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and upadte changelog file. yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0)","title":"standard-version"},{"location":"ecolyo/application/release/#useful-links","text":"Conventional commit doc Lib link","title":"Useful links"},{"location":"ecolyo/application/scaffolding/","text":"In this section, you will find information about the project file structure and the purpose of the main folders. Source Files Folder/File Purpose assets The application's assets, contains fonts, svg and png files components The application's components. components/CommonKit In this folder you'll find global components such as Buttons, Cards, Icons, etc... Many of these components are overrided material-ui components components/Hooks This folder contains the hooks of the application components/App.tsx The root component, it calls the Routes component constants This folder contains constants files such as config.json for the konnectors fluid config, connexionWaitingText.json for the sentences displayed while fetching fluid data, and a folder consumptionConstants that contains json files with constants for consumption calculation and comparison db In this folder, you'll find JSON data used for challenges, ecogestures, and the FAQ. doctypes This folder contains the cozy doctypes, you can see more on Cozy Documentation enum This folder contains all enums like Fluid types, Screen types, and Timesteps. locales This folder contains JSON data used by the translation system i18n provided by Cozy-ui migrations This folder contains all migrations models This folder contains all models notifications This folder contains all mail notifications services This folder contains all the services store This folder contains all actions and reducers classified by component styles The styles folder you'll find a base folder that contains our variables and a components folder that contains components styles targets types utils In this folder you'll find utilitaries methods Configuration Files Folder/File Purpose .eslintrc.js Config file for ESLint gitlab-ci.yml Config file used for Gitlab continuous integration .prettierrc Config file for Prettier extension jest.config.js Config file used by Jest for testing the application manifest.webapp Manifest of the application, used by cozy for the managment of permissions, you can add permissions for doctypes there tsconfig.json Config file for TypeScript","title":"Scaffolding"},{"location":"ecolyo/application/scaffolding/#source-files","text":"Folder/File Purpose assets The application's assets, contains fonts, svg and png files components The application's components. components/CommonKit In this folder you'll find global components such as Buttons, Cards, Icons, etc... Many of these components are overrided material-ui components components/Hooks This folder contains the hooks of the application components/App.tsx The root component, it calls the Routes component constants This folder contains constants files such as config.json for the konnectors fluid config, connexionWaitingText.json for the sentences displayed while fetching fluid data, and a folder consumptionConstants that contains json files with constants for consumption calculation and comparison db In this folder, you'll find JSON data used for challenges, ecogestures, and the FAQ. doctypes This folder contains the cozy doctypes, you can see more on Cozy Documentation enum This folder contains all enums like Fluid types, Screen types, and Timesteps. locales This folder contains JSON data used by the translation system i18n provided by Cozy-ui migrations This folder contains all migrations models This folder contains all models notifications This folder contains all mail notifications services This folder contains all the services store This folder contains all actions and reducers classified by component styles The styles folder you'll find a base folder that contains our variables and a components folder that contains components styles targets types utils In this folder you'll find utilitaries methods","title":"Source Files"},{"location":"ecolyo/application/scaffolding/#configuration-files","text":"Folder/File Purpose .eslintrc.js Config file for ESLint gitlab-ci.yml Config file used for Gitlab continuous integration .prettierrc Config file for Prettier extension jest.config.js Config file used by Jest for testing the application manifest.webapp Manifest of the application, used by cozy for the managment of permissions, you can add permissions for doctypes there tsconfig.json Config file for TypeScript","title":"Configuration Files"},{"location":"ecolyo/ecolyo-agent/introduction/","text":"Ecolyo-Agent is a backoffice for the Ecolyo app that allows to create and edit content for the newsletters sent to the users This project is split into two parts: backend and front-end; each has its own repository If you are a new developer tasked to work on this project, check the setup your environment and launch the application on local to start the application. Repositories Ecolyo-Agent backend gitlab repository Ecolyo-Agent front-end gitlab repository","title":"Introduction"},{"location":"ecolyo/ecolyo-agent/introduction/#repositories","text":"Ecolyo-Agent backend gitlab repository Ecolyo-Agent front-end gitlab repository","title":"Repositories"},{"location":"ecolyo/ecolyo-agent/development/backup/","text":"Principles In the docker-compose.yml, there is a service called \"database-backup\" whose only purpose is to run automatic backups of the database. It is running a crontab that execute the backup.sh script every day at midnight. The dump of the database are stored in folders name like this : \"ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND\". Only the 14 last days are stored. The location of the backup folder on the server is specified in the volumes of the \"database-backup\" service, in the docker-compose file. Backup manually To backup manually, run this command : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/backup.sh Restore manually To restore a specific dump, run this command replacing YEAR etc.. by the date of the wanted backup : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/restore.sh ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND","title":"Backup"},{"location":"ecolyo/ecolyo-agent/development/backup/#principles","text":"In the docker-compose.yml, there is a service called \"database-backup\" whose only purpose is to run automatic backups of the database. It is running a crontab that execute the backup.sh script every day at midnight. The dump of the database are stored in folders name like this : \"ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND\". Only the 14 last days are stored. The location of the backup folder on the server is specified in the volumes of the \"database-backup\" service, in the docker-compose file.","title":"Principles"},{"location":"ecolyo/ecolyo-agent/development/backup/#backup-manually","text":"To backup manually, run this command : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/backup.sh","title":"Backup manually"},{"location":"ecolyo/ecolyo-agent/development/backup/#restore-manually","text":"To restore a specific dump, run this command replacing YEAR etc.. by the date of the wanted backup : docker exec -it ecolyo-agent_database-backup_1 sh /etc/cron.d/restore.sh ecolyo-agent-YEAR-MONTH-DAY-HOUR-MINUTE-SECOND","title":"Restore manually"},{"location":"ecolyo/ecolyo-agent/development/deploy/","text":"This section will allow you to properly deploy Ecolyo-Agent in a production environment Deploy Ecolyo-Agent application To deploy ecolyo-agent application in a production environment, you need to create docker-compose.yml, site.conf and .env files docker-compose.yml version: '3.7' services: nginx: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client:dev restart: unless-stopped ports: - 8080:8080 depends_on: - backend networks: backoffice: volumes: - ./site.conf:/etc/nginx/conf.d/default.conf - ./image-lib:/usr/share/nginx/html/lib database-agent: image: mysql:5 ports: - 3306:3306 networks: backoffice: restart: always environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} healthcheck: test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD interval: 5s timeout: 10s retries: 60 database-backup: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:db-backup networks: backoffice: environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} volumes: - /mnt/local/data/backup:/backup restart: unless-stopped depends_on: database-agent: condition: service_healthy backend: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:dev networks: backoffice: depends_on: database-agent: condition: service_healthy restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ./configs:/app/configs - ./letsencrypt_cache:/app/letsencrypt_cache - ./data:/app/data - ./${IMAGE_FOLDER}:/app/${IMAGE_FOLDER} ports: - ${HTTPS_PORT}:${HTTPS_PORT} - 8190:8090 environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} - CLIENT_SECRET=${CLIENT_SECRET} - AUTH_URL=${AUTH_URL} - IMAGE_FOLDER=${IMAGE_FOLDER} - MOCK_OAUTH2=${MOCK_OAUTH2} - TOKEN_URL=${TOKEN_URL} - USERINFO_URL=${USERINFO_URL} - DEBUG_MODE=${DEBUG_MODE} - DATABASE_USER=${DATABASE_USER} - DATABASE_NAME=${DATABASE_NAME} - DATABASE_PASSWORD=${DATABASE_PASSWORD} - DATABASE_HOST=database-agent networks: backoffice: site.conf server { listen 8080; server_name ecolyo-agent.grandlyon.com; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html =404; } location /api { proxy_pass https://backend:1443/api; } location /OAuth2Login { proxy_pass https://backend:1443/OAuth2Login; } location /OAuth2Callback { proxy_pass https://backend:1443/OAuth2Callback; } location /Logout { proxy_pass https://backend:1443/Logout; } location /swagger { proxy_pass https://backend:1443/swagger; } location /imageNames { proxy_pass https://backend:1443/api/admin/imageNames; } # cozy-doctypes workaround location /email { # if ($arg_serviceName != overview) { return 404; } if ($arg_param !~ \"^\\d+$\") { return 404; } if ($arg_serviceName = \"image\") { rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; #} proxy_pass https://backend:1443/api/common/monthlyReport/$arg_param; # rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; } location ~ ^/assets/(.+\\.(?:gif|jpe?g|svg|png))$ { alias /usr/share/nginx/html/lib/$1; gzip_static on; expires max; add_header Cache-Control public; } } .env In this file, add the variables as described in the env-template file in the git repository To use OAuth2 login ask your client ID and client secret Here is the config to run the app NODE_TLS_REJECT_UNAUTHORIZED = '0' HTTPS=true SSL_CRT_FILE=cert.pem SSL_KEY_FILE=key.pem # Common settings HOSTNAME=your_url.com ADMIN_ROLE=****** DEBUG_MODE=false MOCK_OAUTH2=false HTTPS_PORT=1443 IMAGE_FOLDER=image-lib # Needed to user OAuth2 authentication : REDIRECT_URL=https://${HOSTNAME}:443/OAuth2Callback CLIENT_ID=**get one from your IDP** CLIENT_SECRET=**get one from your IDP** AUTH_URL=**get it from your IDP** TOKEN_URL=**get it from your IDP** USERINFO_URL=**get it from your IDP** LOGOUT_URL=/ # Access to the database DATABASE_USER=****** DATABASE_PASSWORD=******* DATABASE_NAME=backoffice Start the application Then start the app by launching the command : docker-compose up -d To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set","title":"Deploy"},{"location":"ecolyo/ecolyo-agent/development/deploy/#deploy-ecolyo-agent-application","text":"To deploy ecolyo-agent application in a production environment, you need to create docker-compose.yml, site.conf and .env files","title":"Deploy Ecolyo-Agent application"},{"location":"ecolyo/ecolyo-agent/development/deploy/#docker-composeyml","text":"version: '3.7' services: nginx: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client:dev restart: unless-stopped ports: - 8080:8080 depends_on: - backend networks: backoffice: volumes: - ./site.conf:/etc/nginx/conf.d/default.conf - ./image-lib:/usr/share/nginx/html/lib database-agent: image: mysql:5 ports: - 3306:3306 networks: backoffice: restart: always environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} healthcheck: test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD interval: 5s timeout: 10s retries: 60 database-backup: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:db-backup networks: backoffice: environment: MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD} MYSQL_DATABASE: ${DATABASE_NAME} volumes: - /mnt/local/data/backup:/backup restart: unless-stopped depends_on: database-agent: condition: service_healthy backend: image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:dev networks: backoffice: depends_on: database-agent: condition: service_healthy restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ./configs:/app/configs - ./letsencrypt_cache:/app/letsencrypt_cache - ./data:/app/data - ./${IMAGE_FOLDER}:/app/${IMAGE_FOLDER} ports: - ${HTTPS_PORT}:${HTTPS_PORT} - 8190:8090 environment: - HOSTNAME=${HOSTNAME} - HTTPS_PORT=${HTTPS_PORT} - ADMIN_ROLE=${ADMIN_ROLE} - REDIRECT_URL=${REDIRECT_URL} - CLIENT_ID=${CLIENT_ID} - CLIENT_SECRET=${CLIENT_SECRET} - AUTH_URL=${AUTH_URL} - IMAGE_FOLDER=${IMAGE_FOLDER} - MOCK_OAUTH2=${MOCK_OAUTH2} - TOKEN_URL=${TOKEN_URL} - USERINFO_URL=${USERINFO_URL} - DEBUG_MODE=${DEBUG_MODE} - DATABASE_USER=${DATABASE_USER} - DATABASE_NAME=${DATABASE_NAME} - DATABASE_PASSWORD=${DATABASE_PASSWORD} - DATABASE_HOST=database-agent networks: backoffice:","title":"docker-compose.yml"},{"location":"ecolyo/ecolyo-agent/development/deploy/#siteconf","text":"server { listen 8080; server_name ecolyo-agent.grandlyon.com; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html =404; } location /api { proxy_pass https://backend:1443/api; } location /OAuth2Login { proxy_pass https://backend:1443/OAuth2Login; } location /OAuth2Callback { proxy_pass https://backend:1443/OAuth2Callback; } location /Logout { proxy_pass https://backend:1443/Logout; } location /swagger { proxy_pass https://backend:1443/swagger; } location /imageNames { proxy_pass https://backend:1443/api/admin/imageNames; } # cozy-doctypes workaround location /email { # if ($arg_serviceName != overview) { return 404; } if ($arg_param !~ \"^\\d+$\") { return 404; } if ($arg_serviceName = \"image\") { rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; #} proxy_pass https://backend:1443/api/common/monthlyReport/$arg_param; # rewrite ^ /usr/share/nginx/html/lib/$arg_param? permanent; } location ~ ^/assets/(.+\\.(?:gif|jpe?g|svg|png))$ { alias /usr/share/nginx/html/lib/$1; gzip_static on; expires max; add_header Cache-Control public; } }","title":"site.conf"},{"location":"ecolyo/ecolyo-agent/development/deploy/#env","text":"In this file, add the variables as described in the env-template file in the git repository To use OAuth2 login ask your client ID and client secret Here is the config to run the app NODE_TLS_REJECT_UNAUTHORIZED = '0' HTTPS=true SSL_CRT_FILE=cert.pem SSL_KEY_FILE=key.pem # Common settings HOSTNAME=your_url.com ADMIN_ROLE=****** DEBUG_MODE=false MOCK_OAUTH2=false HTTPS_PORT=1443 IMAGE_FOLDER=image-lib # Needed to user OAuth2 authentication : REDIRECT_URL=https://${HOSTNAME}:443/OAuth2Callback CLIENT_ID=**get one from your IDP** CLIENT_SECRET=**get one from your IDP** AUTH_URL=**get it from your IDP** TOKEN_URL=**get it from your IDP** USERINFO_URL=**get it from your IDP** LOGOUT_URL=/ # Access to the database DATABASE_USER=****** DATABASE_PASSWORD=******* DATABASE_NAME=backoffice","title":".env"},{"location":"ecolyo/ecolyo-agent/development/deploy/#start-the-application","text":"Then start the app by launching the command : docker-compose up -d To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set","title":"Start the application"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/","text":"This section will allow you to import the assets used in the newletters from Ecolyo Import assets In the rec or prod server, in the folder scripts , there is the following script, named import-convert-assets.sh . #!/bin/bash # Get env variables . ../.env EMAIL_ASSETS_PATH = \"src/assets/icons/email\" ECOGESTURE_ASSETS_PATH = \"src/assets/icons/visu/ecogesture\" EXPORT_FORMAT = \".png\" pwd = $( pwd ) # Fetch and convert email assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= ${ EMAIL_ASSETS_PATH } \" --output email.tar.gz tar -xf email.tar.gz cd *-email/ $EMAIL_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) $file ; done && rm *.svg cd $pwd # Fetch and convert ecogesture assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= $ECOGESTURE_ASSETS_PATH \" --output ecogesture.tar.gz tar -xf ecogesture.tar.gz cd *-ecogesture/ $ECOGESTURE_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) ${ file } ; done && rm *.svg # Cleanup cd $pwd rm -rf ../ $IMAGE_FOLDER mv *-email/ $EMAIL_ASSETS_PATH ../ $IMAGE_FOLDER mv *-ecogesture/ $ECOGESTURE_ASSETS_PATH ../ $IMAGE_FOLDER /ecogesture rm -rf email.tar.gz ecogesture.tar.gz *-email *-ecogesture # Give ownership to container user chown -R 1000 :1000 ../ $IMAGE_FOLDER To import assets for the ecogesture images, run (inside of scripts folder) sudo sh import-convert-assets.sh Check that a \"image-lib\" folder has been created, that it contains a \"ecogesture\" folder and some PNG images and that the owner of the \"image-lib\" folder is the user id 1000.","title":"Handle assets"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#import-assets","text":"In the rec or prod server, in the folder scripts , there is the following script, named import-convert-assets.sh . #!/bin/bash # Get env variables . ../.env EMAIL_ASSETS_PATH = \"src/assets/icons/email\" ECOGESTURE_ASSETS_PATH = \"src/assets/icons/visu/ecogesture\" EXPORT_FORMAT = \".png\" pwd = $( pwd ) # Fetch and convert email assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= ${ EMAIL_ASSETS_PATH } \" --output email.tar.gz tar -xf email.tar.gz cd *-email/ $EMAIL_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) $file ; done && rm *.svg cd $pwd # Fetch and convert ecogesture assets curl \"https://forge.grandlyon.com/api/v4/projects/409/repository/archive?path= $ECOGESTURE_ASSETS_PATH \" --output ecogesture.tar.gz tar -xf ecogesture.tar.gz cd *-ecogesture/ $ECOGESTURE_ASSETS_PATH && for file in *.svg ; do inkscape -h 200 -w 200 -e $( echo \" $file \" | sed \"s/.svg/ $EXPORT_FORMAT /\" ) ${ file } ; done && rm *.svg # Cleanup cd $pwd rm -rf ../ $IMAGE_FOLDER mv *-email/ $EMAIL_ASSETS_PATH ../ $IMAGE_FOLDER mv *-ecogesture/ $ECOGESTURE_ASSETS_PATH ../ $IMAGE_FOLDER /ecogesture rm -rf email.tar.gz ecogesture.tar.gz *-email *-ecogesture # Give ownership to container user chown -R 1000 :1000 ../ $IMAGE_FOLDER To import assets for the ecogesture images, run (inside of scripts folder) sudo sh import-convert-assets.sh Check that a \"image-lib\" folder has been created, that it contains a \"ecogesture\" folder and some PNG images and that the owner of the \"image-lib\" folder is the user id 1000.","title":"Import assets"},{"location":"ecolyo/ecolyo-agent/functionalities/authentication/","text":"Authentication This backoffice is meant to be used only by the admins of Ecolyo app and so they need to login to edit the newsletters. The protocol used to login is OAuth2 with the Authorization Code grant type ( more info ) Once an admin is connected, he must call the /whoAmI route to access his XSRF-TOKEN and add it in a header named \"XSRF-TOKEN\" for all requests going to the backend. The only routes that can be accessed without authentication are /monthlyReport/year/month and /monthlyReport with GET. They will return all the different sections of a specific or the current newsletter in a single JSON.","title":"Authentication"},{"location":"ecolyo/ecolyo-agent/functionalities/authentication/#authentication","text":"This backoffice is meant to be used only by the admins of Ecolyo app and so they need to login to edit the newsletters. The protocol used to login is OAuth2 with the Authorization Code grant type ( more info ) Once an admin is connected, he must call the /whoAmI route to access his XSRF-TOKEN and add it in a header named \"XSRF-TOKEN\" for all requests going to the backend. The only routes that can be accessed without authentication are /monthlyReport/year/month and /monthlyReport with GET. They will return all the different sections of a specific or the current newsletter in a single JSON.","title":"Authentication"},{"location":"ecolyo/ecolyo-agent/functionalities/general/","text":"Introduction Newsletter The goal is to send newsletters following this design : There are 4 different sections : subject : manages the mail subject monthlyInfo : contains a image URL and some global information monthlyNews : contains an editable title and some information about the novelties poll : contains a question and a link to answer a survey Partners issues This section allow the admin to activate alerts in the ecolyo app when a partners API is down. Admin has to activate the modal switch AND at least one fluid switch to make it work. He also has to set the switches to off position manually when the concerned APIs are back to normal Prices This section manages the prices for each fluid in the ecolyo application. Rules The next price to create is automatically pre-selected by default Only the 2 last prices plus the one to create are editable, the others are just consultable Each fluid has its own date frequency : Electricity : one new price every 6 month (February and August) Water : one new price every year Gas : one new price every month When user creates a new price, the previous price's endDate is set to the new startDate minus 1 minute, so every prices keeps following in time.","title":"General"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#introduction","text":"","title":"Introduction"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#newsletter","text":"The goal is to send newsletters following this design : There are 4 different sections : subject : manages the mail subject monthlyInfo : contains a image URL and some global information monthlyNews : contains an editable title and some information about the novelties poll : contains a question and a link to answer a survey","title":"Newsletter"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#partners-issues","text":"This section allow the admin to activate alerts in the ecolyo app when a partners API is down. Admin has to activate the modal switch AND at least one fluid switch to make it work. He also has to set the switches to off position manually when the concerned APIs are back to normal","title":"Partners issues"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#prices","text":"This section manages the prices for each fluid in the ecolyo application.","title":"Prices"},{"location":"ecolyo/ecolyo-agent/functionalities/general/#rules","text":"The next price to create is automatically pre-selected by default Only the 2 last prices plus the one to create are editable, the others are just consultable Each fluid has its own date frequency : Electricity : one new price every 6 month (February and August) Water : one new price every year Gas : one new price every month When user creates a new price, the previous price's endDate is set to the new startDate minus 1 minute, so every prices keeps following in time.","title":"Rules"},{"location":"ecolyo/ecolyo-agent/functionalities/routes/","text":"Routes The different routes exposed by the backend are described by Swagger documentation. Once the appis deployed, the documentation is accessible at https://HOSTNAME/swagger/index.html","title":"Routes"},{"location":"ecolyo/ecolyo-agent/functionalities/routes/#routes","text":"The different routes exposed by the backend are described by Swagger documentation. Once the appis deployed, the documentation is accessible at https://HOSTNAME/swagger/index.html","title":"Routes"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/","text":"This section will allow you to launch a proper local environment for Ecolyo-Agent Initialisation of the project Clone the project repository Use following commands in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server Installation of the project Installation of node modules To install required node module, open a terminal on the root folder of the backoffice-client project and type the following command: yarn install Local usage Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member. In order to launch the projet in local with the backend working launch the following command yarn local-up This command will launch the app from the docker-compose.local.yml file, which will launch 3 docker images and start the react app with yarn start The backend Go app, from the image located on its GitLab repository The mongo Database, from the DockerHub image The Ngnix server with a local configuration located in nginx/site.conf To stop it properly use yarn local-down This app runs in https, such as the backend, to access it go on https://localhost/ Also make sure you have HTTPS env variable set to true. Do not use the app with the port 3000, you won't be able to login. If you are launching the project from a Windows OS : Make sure to comment the 'extra_hosts' lines in the docker-compose.local file. Otherwise, you you won't be able to access your machine's localhost from the docker container. Backend and Database In order to get Backend documentation, please refer directly to the backend project Nginx The nginx server redirects https requests from front-end to the backend on port 1443. It has two configuration files : nginx/site.conf, used for local development nginx/site.prod.conf, used for production The nginx server needs local ssl certificates in order to run an interact with backend, these certificates are present in the project. Check success To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set Mock OAuth2 server Listening on: http://localhost:8090 Once the application is started, you can access it here: https://localhost Test on alpha In order to test the app on alpha you can do the following steps: Build locally your docker image for the client and/or the server docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag - Push the image docker push registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag Connect to alpha in ssh, go to ecolyo-agent > docker-compose.yml and change the image tag for client and/or server Then launch the app, it will pull automatically the new images docker-compose up -d If you have access denied issue, try to docker login docker login registry.forge.grandlyon.com/web-et-numerique/llle_project/ If you want to update alpha using the same image tag with edited image, just pull manually your new image and rebuild the concerned image docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag docker-compose up -d If you need to work with prices on alpha, you will need to init the prices database. First get the mysql container id docker ps Then get into the container docker exec -it <container-id> bash Then execute the mysql script that imports all the prices in DB mysql --local-infile=1 -uroot -p backoffice < /dbinit/dbinit.sql You will be prompted for the admin password, use the db password set in the .env file. Now you're ready to edit your prices on alpha !","title":"Launch the application on local"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following commands in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server","title":"Clone the project repository"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#installation-of-node-modules","text":"To install required node module, open a terminal on the root folder of the backoffice-client project and type the following command: yarn install","title":"Installation of node modules"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#local-usage","text":"Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member. In order to launch the projet in local with the backend working launch the following command yarn local-up This command will launch the app from the docker-compose.local.yml file, which will launch 3 docker images and start the react app with yarn start The backend Go app, from the image located on its GitLab repository The mongo Database, from the DockerHub image The Ngnix server with a local configuration located in nginx/site.conf To stop it properly use yarn local-down This app runs in https, such as the backend, to access it go on https://localhost/ Also make sure you have HTTPS env variable set to true. Do not use the app with the port 3000, you won't be able to login. If you are launching the project from a Windows OS : Make sure to comment the 'extra_hosts' lines in the docker-compose.local file. Otherwise, you you won't be able to access your machine's localhost from the docker container.","title":"Local usage"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#backend-and-database","text":"In order to get Backend documentation, please refer directly to the backend project","title":"Backend and Database"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#nginx","text":"The nginx server redirects https requests from front-end to the backend on port 1443. It has two configuration files : nginx/site.conf, used for local development nginx/site.prod.conf, used for production The nginx server needs local ssl certificates in order to run an interact with backend, these certificates are present in the project.","title":"Nginx"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#check-success","text":"To check if the application starts successfully, launch the command docker logs backoffice-client_backend_1 You should obtain the following messages: --- Server is starting --- Token signing key set Mock OAuth2 server Listening on: http://localhost:8090 Once the application is started, you can access it here: https://localhost","title":"Check success"},{"location":"ecolyo/ecolyo-agent/getting_started/launch_local_application/#test-on-alpha","text":"In order to test the app on alpha you can do the following steps: Build locally your docker image for the client and/or the server docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag - Push the image docker push registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag Connect to alpha in ssh, go to ecolyo-agent > docker-compose.yml and change the image tag for client and/or server Then launch the app, it will pull automatically the new images docker-compose up -d If you have access denied issue, try to docker login docker login registry.forge.grandlyon.com/web-et-numerique/llle_project/ If you want to update alpha using the same image tag with edited image, just pull manually your new image and rebuild the concerned image docker pull registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-<server/client>:your-tag docker-compose up -d If you need to work with prices on alpha, you will need to init the prices database. First get the mysql container id docker ps Then get into the container docker exec -it <container-id> bash Then execute the mysql script that imports all the prices in DB mysql --local-infile=1 -uroot -p backoffice < /dbinit/dbinit.sql You will be prompted for the admin password, use the db password set in the .env file. Now you're ready to edit your prices on alpha !","title":"Test on alpha"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/","text":"Libraries For this project, we use the libraries below: React Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM Axios HTTP client library It allows to send HTTP request and manage the responses. Lodash javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions Jest Testing library It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product. Sass CSS Preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations. Gorilla/Mux Package for Go that implements a request router and dispatcher for matching incoming requests to their respective handler. It allows us to easily create and manage routes/APIs Swag Package fo Go that converts annotations to Swagger Documentation 2.0. Gorm ORM for Go It allows us to easily communicate between the backend and a relational database","title":"Libraries"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#libraries","text":"For this project, we use the libraries below:","title":"Libraries"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#react","text":"Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM","title":"React"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#axios","text":"HTTP client library It allows to send HTTP request and manage the responses.","title":"Axios"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#lodash","text":"javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions","title":"Lodash"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#jest","text":"Testing library It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product.","title":"Jest"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#sass","text":"CSS Preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.","title":"Sass"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#gorillamux","text":"Package for Go that implements a request router and dispatcher for matching incoming requests to their respective handler. It allows us to easily create and manage routes/APIs","title":"Gorilla/Mux"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#swag","text":"Package fo Go that converts annotations to Swagger Documentation 2.0.","title":"Swag"},{"location":"ecolyo/ecolyo-agent/getting_started/libraries/#gorm","text":"ORM for Go It allows us to easily communicate between the backend and a relational database","title":"Gorm"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/","text":"This section will allow you to install a proper local environment step by step for Ecolyo-Agent using VSCode IDE. VSCode Install VSCode Installation for VSCode can be found here: Installation of VSCode . Extensions Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Go Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension) User settings Open the project with VSCode and add the following code into .vscode/settings.json: { \"workbench.colorCustomizations\": { /* Put anything you like here */ }, \"editor.snippetSuggestions\": \"top\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"editor.formatOnPaste\": true } If this file is not empty, you can simply add the following lines to it: \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, Git The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git (current version : 1.17) Node For this project, Node version 14 is required.Download node-v14 . Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Yarn Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn . Docker Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code. Install Docker Installation of Docker can be found here: Installation of Docker . Install Docker-Compose Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose . Golang Golang (or Go for short) is an open source programming language that makes it easy to build simple, reliable, and efficient software. It is used in this project for the backend. Installation of Go (according to your OS) is explained here: Installation of Go (current version: 1.17).","title":"Setup your environment"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#vscode","text":"","title":"VSCode"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-vscode","text":"Installation for VSCode can be found here: Installation of VSCode .","title":"Install VSCode"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#extensions","text":"Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Go Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension)","title":"Extensions"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#user-settings","text":"Open the project with VSCode and add the following code into .vscode/settings.json: { \"workbench.colorCustomizations\": { /* Put anything you like here */ }, \"editor.snippetSuggestions\": \"top\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0, \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.tabSize\": 2, \"editor.formatOnSave\": true, \"editor.formatOnPaste\": true } If this file is not empty, you can simply add the following lines to it: \"gitlens.advanced.messages\": { \"suppressShowKeyBindingsNotice\": true }, \"breadcrumbs.enabled\": true, \"workbench.settings.editor\": \"json\", \"editor.formatOnSave\": true, \"diffEditor.ignoreTrimWhitespace\": false, \"window.zoomLevel\": 0,","title":"User settings"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#git","text":"The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git (current version : 1.17)","title":"Git"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#node","text":"For this project, Node version 14 is required.Download node-v14 . Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine.","title":"Node"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#yarn","text":"Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn .","title":"Yarn"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#docker","text":"Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.","title":"Docker"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-docker","text":"Installation of Docker can be found here: Installation of Docker .","title":"Install Docker"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#install-docker-compose","text":"Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Install Docker-Compose"},{"location":"ecolyo/ecolyo-agent/getting_started/setup_your_environment/#golang","text":"Golang (or Go for short) is an open source programming language that makes it easy to build simple, reliable, and efficient software. It is used in this project for the backend. Installation of Go (according to your OS) is explained here: Installation of Go (current version: 1.17).","title":"Golang"},{"location":"ecolyo/functionalities/analysis/","text":"This section explains the analysis screen and how information are displayed. Description The analysis screen shows the user a recap of his consumption of the last month. It allows him to compare his consumption with the previous month and also with an average consumption based on his profile if he completed it. Graph On the left side, the user can see his consumption for the konnected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate. Also, when user has the possibility to switch the comparison with the average profile or the ideal profile. For now, the ideal profile just represents the average profile's consumption minus 10%. Each line of the graph is handled by the AnalysisConsumptionRow component. It displays the consumption for a given fluid, a draws a bar sized in comparison with the total and applies the 10% ideal coefficient when user clicks on his ideal consumption. Note that only the consumption related to a connected fluid are taken for the calculation of the total price of the ideal or average consumption, even if the consumption indicators are shown for the non-connected fluids. (it is given a indicator for the user, considering he may use this fluid but doesn't have a connected device) Calculation The Consumption Service allows us to get the user's consumption on the given month, and the Performance Indicator Service allows us to get the comparative indicator between the currently displayed month and the previous one. In order to get the accurate consumption estimation, we use the fluidForecast stored in the user's profile. You can see more about it in the next section : ProfileType Navigation Users have the possibility to navigate between current and previous analysis, month by month, using the DateNavigator at the top of the screen. It is not possible to navigate after the last analysis (which is set the next month + 3 days in order to have a month with complete data). For example, the 3rd of June, a user will be able to see his analysis of Mai. Users won't be blocked to navigate in previous dates, and if there is no analysis to display, we use the same behavior than in the graph : we display dashes instead of data. Notification Each month, the user will receive a notification to inform him he can consult his new analysis if he activated it in the option page.","title":"Analysis"},{"location":"ecolyo/functionalities/analysis/#description","text":"The analysis screen shows the user a recap of his consumption of the last month. It allows him to compare his consumption with the previous month and also with an average consumption based on his profile if he completed it.","title":"Description"},{"location":"ecolyo/functionalities/analysis/#graph","text":"On the left side, the user can see his consumption for the konnected fluids. On the right side, there is by default the consumption of default profile until user completes his own. Once it is done, the comparison is much more accurate. Also, when user has the possibility to switch the comparison with the average profile or the ideal profile. For now, the ideal profile just represents the average profile's consumption minus 10%. Each line of the graph is handled by the AnalysisConsumptionRow component. It displays the consumption for a given fluid, a draws a bar sized in comparison with the total and applies the 10% ideal coefficient when user clicks on his ideal consumption. Note that only the consumption related to a connected fluid are taken for the calculation of the total price of the ideal or average consumption, even if the consumption indicators are shown for the non-connected fluids. (it is given a indicator for the user, considering he may use this fluid but doesn't have a connected device)","title":"Graph"},{"location":"ecolyo/functionalities/analysis/#calculation","text":"The Consumption Service allows us to get the user's consumption on the given month, and the Performance Indicator Service allows us to get the comparative indicator between the currently displayed month and the previous one. In order to get the accurate consumption estimation, we use the fluidForecast stored in the user's profile. You can see more about it in the next section : ProfileType","title":"Calculation"},{"location":"ecolyo/functionalities/analysis/#navigation","text":"Users have the possibility to navigate between current and previous analysis, month by month, using the DateNavigator at the top of the screen. It is not possible to navigate after the last analysis (which is set the next month + 3 days in order to have a month with complete data). For example, the 3rd of June, a user will be able to see his analysis of Mai. Users won't be blocked to navigate in previous dates, and if there is no analysis to display, we use the same behavior than in the graph : we display dashes instead of data.","title":"Navigation"},{"location":"ecolyo/functionalities/analysis/#notification","text":"Each month, the user will receive a notification to inform him he can consult his new analysis if he activated it in the option page.","title":"Notification"},{"location":"ecolyo/functionalities/challenge/","text":"This section explain all the functionalities in the challenge part Quiz A quiz includes 4 basic questions and one custom question. Process Questions and answers are generated in random order. At the begining of the quiz, the user have to select an answer and click validate. Then, he sees the right answer and a modal with the explanation. After this modal, he goes to the next question. Depending on the answer, the question result state is set either to correct or incorrect. If it is a right answer, the quiz result is incremented by one. A user can stop during a quiz and picks up where he left off. To define where the user left off, we have to check if at least one of the question result status is unlocked. Once the custom question is answered, the quiz state is set to done. Then, the user sees his result and his earned stars. He can also retry or go back to the challenge page. Basic Question All basics Questions are created in the quizEntity.json. We have to add : Field Description questionLabel Label of the question answers Array of 3 answers (answerLabel, isTrue) description Explains the question source Source of the explanation Custom Question At the end of every quiz, we're creating a custom question. Here are the fields used to create a custom question Field Type Description type CustomQuestionType Type of custom qusetion: DATE or MAXLOAD or AVERAGE. timeStep TimeStep Time step of the result value (DAY / WEEK / MONTH / YEAR). For MAXLOAD or AVERAGE type, it represents daily / weekly / monthly / yearly average. interval TimeStep Interval in which the data will be searched (DAY / WEEK / MONTH / YEAR) period CustomPeriod Case day / month / year: Use to define a specific period for the interval { day? / month? / year? }. Case weekday: Only usable with AVERAGE type and DAY timestep: Allow to specify a weekday on which average is made. If used with another type, period will not be taken into account. If not assigned the period will be the last interval (example: last week) singleFluid boolean Indicate if all connected fluid should be taken into account. If set to true only the first connected fluid will be taken into account in this order: electricity, gas, water. #unit and #fluid in the question label will be replace by the unit and the name of the fluid result UserQuizState Indicate the state of the custom question (UNLOCKED, CORRECT, UNCORRECT) Calculation of custom question is done by combination of all parameters: Type DATE If period is empty. Retrieve the date of day/month/year (define by timeStep ) from the last week, month, year (define by interval ), if there is no data in this interval, then it will go back to a previous interval, up to a maximum of 6 months example: What day did I consumme the most on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false example: What day did I consumme the most #fluid in #unit on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = true If period is not empty Retrieve the date of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: What month did I consumme the most on year 2020 ? type = CustomQuestionType.DATA timeStep = TimeStep.MONTH interval = TimeStep.YEAR period = { year: 2020 } singleFluid = false Type MAXLOAD If period is empty Retrieve the maxload value of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily max consumption on the last week ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the maxload value of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily max consumption on january 2020 ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false Type AVERAGE If period is empty Retrieve the average of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily average consumption on last week ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the average of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily average consumption on january 2020 ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false If period is weekday Retrieve the average of the weekday from a week, month, year (define by interval ). example: Which is your daily average consumption on wednesdays of last month? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { weekday: 3 } singleFluid = false Wrong answers After defining the right answer, two random answers are generated depending of the custom question type: type DATE Two dates is generated one, a day before the correct date and the other, a day after. type MAXLOAD or AVERAGE Two random value is generated by applying a coefficient based on the correct answer. This coefficient is randomly included between 0.7 and 0.9 (for the first value) or between 1.1 and 1.3 (for the second value) Exploration Exploration is a feature where the user has to do an action in order to help him discover all features from ecolyo. They are 4 types of actions: DECLARATIVE : The user has to do something outside of the app => No way for the app to know if the user did it so we trust him. ACTION : Action whitin the app. When the user finishes he gets a notification. CONSUMPTION : He has to do something in his consumption view. ECOGESTURE : He needs to look at a specific Ecogesture. In order to check if an exploration (which is not declarative) is done, a hook called useExploration is used.It is called on component that has to check if an exploration is done. This hook called exploration service to check exploration by passing two parameters (the current challenge and the user exploration id associated with the exploration id of the current challenge). This check is done only if: There is a current challenge exploration.id of the current challenge is equal to the user exploration id exploration.state is ONGOING Depends on the type of an exploration, either the exploration remains in progress until it is fully done or it ends. When the user finish the exploration, he gets a success message and five more stars are added to his challenge progression. Action Action is a feature which in the user has to apply an ecogesture for a given duration in order to reduce his consumption. An action refers to the model UserAction in the app, and is an extention of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. UserAction { ecogesture: Ecogesture | null state: UserActionState startDate: DateTime | null } Unlike the exploration, duel and quiz, there is no relationship for an action in the ChallengeEntity model, given that the action is picked by the user. So once it is picked, it is directly stored in the current UserChallenge . When a user launches an action, there is several possible cases : The user has not completed his consumption profile If the user's profile has never been completed, the application will purpose him the default action list which is defined in the action service. The first one of this list will be shown at first, and if the user wants to pick another one, he'll have the choice between the three ecogestures of the default list. The user has completed his consumption profile If the user has completed his profile, the application will purpose him a list of three custom ecogestures. The list is built the following way : First we look for the action that haven't been done yet We pick only the actions that are available for the user's connected fluids We pick the action that are appliable during the current season. At this moment, if the list is smaller than 3, we complete it with actions whose value for property Season is NONE If the list is still smaller than 3 after this, we complete with default actions (This case is rare) Finally, we sort the list of action by efficency and then difficulty. We put the most efficient actions and with the lowest difficulty in first. At any moment of an action, a user can consult his progress through a clock icon and the ending date of his action. The accomplishment of an action is only conditionned by the duration. Once the user completes an action, he'll see a notification on the app and then win his five stars when he comes back to the action screen. Duel On launch In order to find a valid reference period we search for a period which is defined by the duel duration. We check the most recent period first if it's complete and then we go farther and farther in time if the ones before got missing values. We also define a threshold for a maximum old period 6 months for the moment - hard coded. If the thresold is reached and no valid period was found, we alert the user that he can't launch the duel and have to wait before he can retry this process. On going Every time the user goes into the duel mode, we are checking if the duel is finished. if we have retrieved all data to calculate the user consumption on the duel duration, the duel is done. In order to not block the user if a value is mising, we are also setting the duel as done when we reach the startDate + delay in day to retrieve the data (based on the fluid) + 1 day. In this case the user consumption is done on known values. On finish Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge. Challenges We can find the file challengeEntity.json in the /db folder. This file contains an array of challenges, and each of them includes relationships to duels, quiz, missions and actions. For more precision about the data managment system you can refer the picture in the Initialization section","title":"Challenge"},{"location":"ecolyo/functionalities/challenge/#quiz","text":"A quiz includes 4 basic questions and one custom question.","title":"Quiz"},{"location":"ecolyo/functionalities/challenge/#process","text":"Questions and answers are generated in random order. At the begining of the quiz, the user have to select an answer and click validate. Then, he sees the right answer and a modal with the explanation. After this modal, he goes to the next question. Depending on the answer, the question result state is set either to correct or incorrect. If it is a right answer, the quiz result is incremented by one. A user can stop during a quiz and picks up where he left off. To define where the user left off, we have to check if at least one of the question result status is unlocked. Once the custom question is answered, the quiz state is set to done. Then, the user sees his result and his earned stars. He can also retry or go back to the challenge page.","title":"Process"},{"location":"ecolyo/functionalities/challenge/#basic-question","text":"All basics Questions are created in the quizEntity.json. We have to add : Field Description questionLabel Label of the question answers Array of 3 answers (answerLabel, isTrue) description Explains the question source Source of the explanation","title":"Basic Question"},{"location":"ecolyo/functionalities/challenge/#custom-question","text":"At the end of every quiz, we're creating a custom question. Here are the fields used to create a custom question Field Type Description type CustomQuestionType Type of custom qusetion: DATE or MAXLOAD or AVERAGE. timeStep TimeStep Time step of the result value (DAY / WEEK / MONTH / YEAR). For MAXLOAD or AVERAGE type, it represents daily / weekly / monthly / yearly average. interval TimeStep Interval in which the data will be searched (DAY / WEEK / MONTH / YEAR) period CustomPeriod Case day / month / year: Use to define a specific period for the interval { day? / month? / year? }. Case weekday: Only usable with AVERAGE type and DAY timestep: Allow to specify a weekday on which average is made. If used with another type, period will not be taken into account. If not assigned the period will be the last interval (example: last week) singleFluid boolean Indicate if all connected fluid should be taken into account. If set to true only the first connected fluid will be taken into account in this order: electricity, gas, water. #unit and #fluid in the question label will be replace by the unit and the name of the fluid result UserQuizState Indicate the state of the custom question (UNLOCKED, CORRECT, UNCORRECT) Calculation of custom question is done by combination of all parameters:","title":"Custom Question"},{"location":"ecolyo/functionalities/challenge/#type-date","text":"If period is empty. Retrieve the date of day/month/year (define by timeStep ) from the last week, month, year (define by interval ), if there is no data in this interval, then it will go back to a previous interval, up to a maximum of 6 months example: What day did I consumme the most on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false example: What day did I consumme the most #fluid in #unit on the last week ? type = CustomQuestionType.DATA timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = true If period is not empty Retrieve the date of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: What month did I consumme the most on year 2020 ? type = CustomQuestionType.DATA timeStep = TimeStep.MONTH interval = TimeStep.YEAR period = { year: 2020 } singleFluid = false","title":"Type DATE"},{"location":"ecolyo/functionalities/challenge/#type-maxload","text":"If period is empty Retrieve the maxload value of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily max consumption on the last week ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the maxload value of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily max consumption on january 2020 ? type = CustomQuestionType.MAXLOAD timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false","title":"Type MAXLOAD"},{"location":"ecolyo/functionalities/challenge/#type-average","text":"If period is empty Retrieve the average of day/month/year (define by timeStep ) from the last week, month, year (define by interval ). example: Which is your daily average consumption on last week ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.WEEK period = {} singleFluid = false If period is not empty Retrieve the average of day/month/year (define by timeStep ) from a week, month, year (define by interval ) of period example: Which is your daily average consumption on january 2020 ? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { month: 1, year: 2020 } singleFluid = false If period is weekday Retrieve the average of the weekday from a week, month, year (define by interval ). example: Which is your daily average consumption on wednesdays of last month? type = CustomQuestionType.AVERAGE timeStep = TimeStep.DAY interval = TimeStep.MONTH period = { weekday: 3 } singleFluid = false","title":"Type AVERAGE"},{"location":"ecolyo/functionalities/challenge/#wrong-answers","text":"After defining the right answer, two random answers are generated depending of the custom question type: type DATE Two dates is generated one, a day before the correct date and the other, a day after. type MAXLOAD or AVERAGE Two random value is generated by applying a coefficient based on the correct answer. This coefficient is randomly included between 0.7 and 0.9 (for the first value) or between 1.1 and 1.3 (for the second value)","title":"Wrong answers"},{"location":"ecolyo/functionalities/challenge/#exploration","text":"Exploration is a feature where the user has to do an action in order to help him discover all features from ecolyo. They are 4 types of actions: DECLARATIVE : The user has to do something outside of the app => No way for the app to know if the user did it so we trust him. ACTION : Action whitin the app. When the user finishes he gets a notification. CONSUMPTION : He has to do something in his consumption view. ECOGESTURE : He needs to look at a specific Ecogesture. In order to check if an exploration (which is not declarative) is done, a hook called useExploration is used.It is called on component that has to check if an exploration is done. This hook called exploration service to check exploration by passing two parameters (the current challenge and the user exploration id associated with the exploration id of the current challenge). This check is done only if: There is a current challenge exploration.id of the current challenge is equal to the user exploration id exploration.state is ONGOING Depends on the type of an exploration, either the exploration remains in progress until it is fully done or it ends. When the user finish the exploration, he gets a success message and five more stars are added to his challenge progression.","title":"Exploration"},{"location":"ecolyo/functionalities/challenge/#action","text":"Action is a feature which in the user has to apply an ecogesture for a given duration in order to reduce his consumption. An action refers to the model UserAction in the app, and is an extention of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. UserAction { ecogesture: Ecogesture | null state: UserActionState startDate: DateTime | null } Unlike the exploration, duel and quiz, there is no relationship for an action in the ChallengeEntity model, given that the action is picked by the user. So once it is picked, it is directly stored in the current UserChallenge . When a user launches an action, there is several possible cases :","title":"Action"},{"location":"ecolyo/functionalities/challenge/#the-user-has-not-completed-his-consumption-profile","text":"If the user's profile has never been completed, the application will purpose him the default action list which is defined in the action service. The first one of this list will be shown at first, and if the user wants to pick another one, he'll have the choice between the three ecogestures of the default list.","title":"The user has not completed his consumption profile"},{"location":"ecolyo/functionalities/challenge/#the-user-has-completed-his-consumption-profile","text":"If the user has completed his profile, the application will purpose him a list of three custom ecogestures. The list is built the following way : First we look for the action that haven't been done yet We pick only the actions that are available for the user's connected fluids We pick the action that are appliable during the current season. At this moment, if the list is smaller than 3, we complete it with actions whose value for property Season is NONE If the list is still smaller than 3 after this, we complete with default actions (This case is rare) Finally, we sort the list of action by efficency and then difficulty. We put the most efficient actions and with the lowest difficulty in first. At any moment of an action, a user can consult his progress through a clock icon and the ending date of his action. The accomplishment of an action is only conditionned by the duration. Once the user completes an action, he'll see a notification on the app and then win his five stars when he comes back to the action screen.","title":"The user has completed his consumption profile"},{"location":"ecolyo/functionalities/challenge/#duel","text":"","title":"Duel"},{"location":"ecolyo/functionalities/challenge/#on-launch","text":"In order to find a valid reference period we search for a period which is defined by the duel duration. We check the most recent period first if it's complete and then we go farther and farther in time if the ones before got missing values. We also define a threshold for a maximum old period 6 months for the moment - hard coded. If the thresold is reached and no valid period was found, we alert the user that he can't launch the duel and have to wait before he can retry this process.","title":"On launch"},{"location":"ecolyo/functionalities/challenge/#on-going","text":"Every time the user goes into the duel mode, we are checking if the duel is finished. if we have retrieved all data to calculate the user consumption on the duel duration, the duel is done. In order to not block the user if a value is mising, we are also setting the duel as done when we reach the startDate + delay in day to retrieve the data (based on the fluid) + 1 day. In this case the user consumption is done on known values.","title":"On going"},{"location":"ecolyo/functionalities/challenge/#on-finish","text":"Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge.","title":"On finish"},{"location":"ecolyo/functionalities/challenge/#challenges","text":"We can find the file challengeEntity.json in the /db folder. This file contains an array of challenges, and each of them includes relationships to duels, quiz, missions and actions. For more precision about the data managment system you can refer the picture in the Initialization section","title":"Challenges"},{"location":"ecolyo/functionalities/consumption/","text":"Consumption Ecolyo allow user to see its consumption in two way: globally with the mutlifluid view that displays euro consumptions more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu All consumption information are retrieved and calculated by services from the application. Time step Different time steps can be selected by the user which will display different period on the graph according to the time step. Day: display data at half-an-hour step on a period of one day Week: display data at daily step on a period of a week Month: display data at daily step on a period of a month Year: display data at monthly step on a period of a year 5 years: display data at yearly step on a period of 5 years (5 last years) Data Interval For each fluid, we have an upcoming data interval depending on the energy provider API's. When we check the data, we display directly the data or a specific message according to the last data we have in comparison with the actual date and the last data date. We rely on these 3 intervals to show different messages : For Enedis, the interval is 3 days For GRDF, the interval is 5 days For EGL, the interval is 5 days ConsumptionView Description This view is the main view of the application. It displays an agreggation view of all connected fluids. It is the entrypoint to several children components that each handles a particular feature : DateNavigator FluidButtons FluidChart ConsumptionDetails KonnectorViewerList / KonnectorViewerCard The submenu (FluidButtons), allows the user to switch between the different fluids and the multifluid view. Rules If no fluids are connected, this view will display the multifluid view with the KonnectorViewerList component which shows buttons that allow user to connect its first fluids. These buttons redirects to the chosen fluid section with the connection form. If at least one fluid is connected, the multi fluid view and the connected fluids views are shown (electricity, water, gas). For the multifluid view, Fluids are displayed in multi fluid color and in euro Fluid is displayed in the given fluid color and unit (kWh for electricity and gaz, l for water) TimeStep available are the following: week, month, year, 5 years and day for electricity fluid If user has selected day time step and change the fluid, the week time step will be selected by default. DateNavigator Description The component allows the user to navigate through the selected timestep (week by week, month by month, etc.) Rules If no fluid is connected, the navigation is locked By default, the date is set to the lastDataDate. Navigation is locked above the current date. FluidButtons Description The component allows the user to navigate through the different fluid views (multifluid, electricity, water, gaz) Rules If a Konnector is errored or its data is outdated, we show a red cross on the fluid icon If the fluid is not connected we show a \"turn on\" icon Icons have an active state. (They are coloured when selected) FluidChart Description This component is the one that shows the user its consumption, according to the selected fluid, timestep and date. It is splitted in 3 distinct parts: The ConsumptionVisualier The FluidSlides The TimeStep Navigator Rules Component Rules ConsumptionVisualizer Calls the DataloadConsumptionVisualizer component that shows the dataload of the selected timeStep and fluid For multifluid, we show the total consumption of all connected fluid, and the consumption fluid by fluid, all in \u20ac We display a message according to the data state as explained in the DataLoad Consumption Visualizer FluidSlides This component calls the fluidSwipe component which is handled by the library react-swipeable-views , and allows the user to swipe accross the selected timestep. This library loads the slides before and after the current slide, so we reduce the loading time between slides. TimeStepSelector This component allows the user to change the current Timestep, or to return to today's date with a button DataLoad Consumption Visualizer Description This view displays the load of a specified fluid (electricity, water, gas) or the total consumption on the multifluid screen. The display will be done in function of the data state. Rules to define data state The data state is define in the \"ConsumptionFormatter\" service following theses rules : For single fluid Condition State Before the first data available EMPTY Between the first and last data available & value of load is not empty VALID Between the first and last data available & value of load is empty HOLE After the last data available & Before today & in the dataDelayOffset period UPCOMING After the last data available & Before today & not in the dataDelayOffset period MISSING After today COMING For multifluid Condition State All fluids have empty data AGGREGATED_EMPTY At least one fluid have a data and another fluids with empty data AGGREGATED_WITH_EMPTY All fluids have valid data AGGREGATED_VALID All fluid have a hole or missing data AGGREGATED_HOLE_OR_MISSING At least one fluid have a data and another fluids with a missing or hole data AGGREGATED_WITH_HOLE_OR_MISSING At least one fluid have upcoming or coming data and other fluid doesn\u2019t have missing or hole data AGGREGATED_WITH_COMING All fluid have coming data AGGREGATED_COMING Display of the specific cases (component: DataloadNoValue) This display appear instead of the traditionnal one (described below). It is used to display a general message which override the value. Here are the rules : Condition Displayed label Comments Single fluid && dataload state = EMPTY Pas de donn\u00e9es Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pas de donn\u00e9es Single fluid && dataload state = MISSING Donn\u00e9es manquantes Displayed in red and clickable (scroll to the konnector card) Single fluid && dataload state = UPCOMING \u00c0 venir Single fluid && dataload state = COMING \u00c0 venir Multi fluid && dataload state = AGGREGATED_EMPTY Pas de donn\u00e9es Multi fluid && dataload state = AGGREGATED_WITH_EMPTY - Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Donn\u00e9es manquantes Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING - Multi fluid && dataload state = AGGREGATED_COMING \u00c0 venir Display of the load values In function of the fluid type (single or multi) and of the data state, the display will be adapted. Display of the main value (component: DataloadSectionValue) Used to display the load or price in function of following rules : Condition Displayed information Single fluid && dataload value < 1000 Display the load Single fluid && dataload value >= 1000 Display the load in Mega unit Multifluid without comparison Display the load converted in euro and a link to display the Estimated Modal information Multifluid with comparison Display the load converted in euro Display of the detail value (component: DataloadSectionDetail) Used to display the detail just below the main value. The information displayed are : Condition Displayed information Single fluid Display the load converted in euro Multifluid without comparison Display the load converted in euro for each available fluid Multifluid with comparison Display nothing Information (component: InfoDataConsumptionVisualizer) In addition of the value / load / message displayed, we can displayed an additionnal information. Condition Displayed label Comments Single fluid && dataload state = EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = MISSING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = UPCOMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = COMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Multi fluid && dataload state = AGGREGATED_EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_COMING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Comparison The user can compare its data with a previous period using a switch which will display the previous period on the same chart. The chart scale will adapt to the max load displayed between the actualData and the comparisonData Konnector Viewer Card This component shows the konnector's state and allows the user to connect, delete, or update a konnector Rules If the fluid is konnected, this component will shows the konnector state at the end of the consumption page If the fluid is not konnected, it will show the connection form If the konnector is in error or its data is outdated, it will display the number of days since the data is outdated If the error is a login error (eg: user consent is revocated), it will show a specific message If the data is outdated but the user has already triggered an update today, we will show a message that informs the user that the issue is probably related to the energy provider","title":"Consumption"},{"location":"ecolyo/functionalities/consumption/#consumption","text":"Ecolyo allow user to see its consumption in two way: globally with the mutlifluid view that displays euro consumptions more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu All consumption information are retrieved and calculated by services from the application.","title":"Consumption"},{"location":"ecolyo/functionalities/consumption/#time-step","text":"Different time steps can be selected by the user which will display different period on the graph according to the time step. Day: display data at half-an-hour step on a period of one day Week: display data at daily step on a period of a week Month: display data at daily step on a period of a month Year: display data at monthly step on a period of a year 5 years: display data at yearly step on a period of 5 years (5 last years)","title":"Time step"},{"location":"ecolyo/functionalities/consumption/#data-interval","text":"For each fluid, we have an upcoming data interval depending on the energy provider API's. When we check the data, we display directly the data or a specific message according to the last data we have in comparison with the actual date and the last data date. We rely on these 3 intervals to show different messages : For Enedis, the interval is 3 days For GRDF, the interval is 5 days For EGL, the interval is 5 days","title":"Data Interval"},{"location":"ecolyo/functionalities/consumption/#consumptionview","text":"","title":"ConsumptionView"},{"location":"ecolyo/functionalities/consumption/#description","text":"This view is the main view of the application. It displays an agreggation view of all connected fluids. It is the entrypoint to several children components that each handles a particular feature : DateNavigator FluidButtons FluidChart ConsumptionDetails KonnectorViewerList / KonnectorViewerCard The submenu (FluidButtons), allows the user to switch between the different fluids and the multifluid view.","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules","text":"If no fluids are connected, this view will display the multifluid view with the KonnectorViewerList component which shows buttons that allow user to connect its first fluids. These buttons redirects to the chosen fluid section with the connection form. If at least one fluid is connected, the multi fluid view and the connected fluids views are shown (electricity, water, gas). For the multifluid view, Fluids are displayed in multi fluid color and in euro Fluid is displayed in the given fluid color and unit (kWh for electricity and gaz, l for water) TimeStep available are the following: week, month, year, 5 years and day for electricity fluid If user has selected day time step and change the fluid, the week time step will be selected by default.","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#datenavigator","text":"","title":"DateNavigator"},{"location":"ecolyo/functionalities/consumption/#description_1","text":"The component allows the user to navigate through the selected timestep (week by week, month by month, etc.)","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_1","text":"If no fluid is connected, the navigation is locked By default, the date is set to the lastDataDate. Navigation is locked above the current date.","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#fluidbuttons","text":"","title":"FluidButtons"},{"location":"ecolyo/functionalities/consumption/#description_2","text":"The component allows the user to navigate through the different fluid views (multifluid, electricity, water, gaz)","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_2","text":"If a Konnector is errored or its data is outdated, we show a red cross on the fluid icon If the fluid is not connected we show a \"turn on\" icon Icons have an active state. (They are coloured when selected)","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#fluidchart","text":"","title":"FluidChart"},{"location":"ecolyo/functionalities/consumption/#description_3","text":"This component is the one that shows the user its consumption, according to the selected fluid, timestep and date. It is splitted in 3 distinct parts: The ConsumptionVisualier The FluidSlides The TimeStep Navigator","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules_3","text":"Component Rules ConsumptionVisualizer Calls the DataloadConsumptionVisualizer component that shows the dataload of the selected timeStep and fluid For multifluid, we show the total consumption of all connected fluid, and the consumption fluid by fluid, all in \u20ac We display a message according to the data state as explained in the DataLoad Consumption Visualizer FluidSlides This component calls the fluidSwipe component which is handled by the library react-swipeable-views , and allows the user to swipe accross the selected timestep. This library loads the slides before and after the current slide, so we reduce the loading time between slides. TimeStepSelector This component allows the user to change the current Timestep, or to return to today's date with a button","title":"Rules"},{"location":"ecolyo/functionalities/consumption/#dataload-consumption-visualizer","text":"","title":"DataLoad Consumption Visualizer"},{"location":"ecolyo/functionalities/consumption/#description_4","text":"This view displays the load of a specified fluid (electricity, water, gas) or the total consumption on the multifluid screen. The display will be done in function of the data state.","title":"Description"},{"location":"ecolyo/functionalities/consumption/#rules-to-define-data-state","text":"The data state is define in the \"ConsumptionFormatter\" service following theses rules :","title":"Rules to define data state"},{"location":"ecolyo/functionalities/consumption/#for-single-fluid","text":"Condition State Before the first data available EMPTY Between the first and last data available & value of load is not empty VALID Between the first and last data available & value of load is empty HOLE After the last data available & Before today & in the dataDelayOffset period UPCOMING After the last data available & Before today & not in the dataDelayOffset period MISSING After today COMING","title":"For single fluid"},{"location":"ecolyo/functionalities/consumption/#for-multifluid","text":"Condition State All fluids have empty data AGGREGATED_EMPTY At least one fluid have a data and another fluids with empty data AGGREGATED_WITH_EMPTY All fluids have valid data AGGREGATED_VALID All fluid have a hole or missing data AGGREGATED_HOLE_OR_MISSING At least one fluid have a data and another fluids with a missing or hole data AGGREGATED_WITH_HOLE_OR_MISSING At least one fluid have upcoming or coming data and other fluid doesn\u2019t have missing or hole data AGGREGATED_WITH_COMING All fluid have coming data AGGREGATED_COMING","title":"For multifluid"},{"location":"ecolyo/functionalities/consumption/#display-of-the-specific-cases-component-dataloadnovalue","text":"This display appear instead of the traditionnal one (described below). It is used to display a general message which override the value. Here are the rules : Condition Displayed label Comments Single fluid && dataload state = EMPTY Pas de donn\u00e9es Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pas de donn\u00e9es Single fluid && dataload state = MISSING Donn\u00e9es manquantes Displayed in red and clickable (scroll to the konnector card) Single fluid && dataload state = UPCOMING \u00c0 venir Single fluid && dataload state = COMING \u00c0 venir Multi fluid && dataload state = AGGREGATED_EMPTY Pas de donn\u00e9es Multi fluid && dataload state = AGGREGATED_WITH_EMPTY - Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Donn\u00e9es manquantes Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING - Multi fluid && dataload state = AGGREGATED_COMING \u00c0 venir","title":"Display of the specific cases (component: DataloadNoValue)"},{"location":"ecolyo/functionalities/consumption/#display-of-the-load-values","text":"In function of the fluid type (single or multi) and of the data state, the display will be adapted.","title":"Display of the load values"},{"location":"ecolyo/functionalities/consumption/#display-of-the-main-value-component-dataloadsectionvalue","text":"Used to display the load or price in function of following rules : Condition Displayed information Single fluid && dataload value < 1000 Display the load Single fluid && dataload value >= 1000 Display the load in Mega unit Multifluid without comparison Display the load converted in euro and a link to display the Estimated Modal information Multifluid with comparison Display the load converted in euro","title":"Display of the main value (component: DataloadSectionValue)"},{"location":"ecolyo/functionalities/consumption/#display-of-the-detail-value-component-dataloadsectiondetail","text":"Used to display the detail just below the main value. The information displayed are : Condition Displayed information Single fluid Display the load converted in euro Multifluid without comparison Display the load converted in euro for each available fluid Multifluid with comparison Display nothing","title":"Display of the detail value (component: DataloadSectionDetail)"},{"location":"ecolyo/functionalities/consumption/#information-component-infodataconsumptionvisualizer","text":"In addition of the value / load / message displayed, we can displayed an additionnal information. Condition Displayed label Comments Single fluid && dataload state = EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = VALID - Single fluid && dataload state = HOLE Pourquoi n\u2019ai-je pas de donn\u00e9es ? Single fluid && dataload state = MISSING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = UPCOMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Single fluid && dataload state = COMING Derni\u00e8res donn\u00e9es disponibles : XX/XX/XX Multi fluid && dataload state = AGGREGATED_EMPTY Pourquoi n\u2019ai-je pas de donn\u00e9es ? Multi fluid && dataload state = AGGREGATED_VALID - Multi fluid && dataload state = AGGREGATED_WITH_COMING - Multi fluid && dataload state = AGGREGATED_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_WITH_HOLE_OR_MISSING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX Multi fluid && dataload state = AGGREGATED_COMING Derni\u00e8res donn\u00e9es compl\u00e8tes : XX/XX/XX","title":"Information (component: InfoDataConsumptionVisualizer)"},{"location":"ecolyo/functionalities/consumption/#comparison","text":"The user can compare its data with a previous period using a switch which will display the previous period on the same chart. The chart scale will adapt to the max load displayed between the actualData and the comparisonData","title":"Comparison"},{"location":"ecolyo/functionalities/consumption/#konnector-viewer-card","text":"This component shows the konnector's state and allows the user to connect, delete, or update a konnector","title":"Konnector Viewer Card"},{"location":"ecolyo/functionalities/consumption/#rules_4","text":"If the fluid is konnected, this component will shows the konnector state at the end of the consumption page If the fluid is not konnected, it will show the connection form If the konnector is in error or its data is outdated, it will display the number of days since the data is outdated If the error is a login error (eg: user consent is revocated), it will show a specific message If the data is outdated but the user has already triggered an update today, we will show a message that informs the user that the issue is probably related to the energy provider","title":"Rules"},{"location":"ecolyo/functionalities/dacc/","text":"DACC What is DACC ? A cozy blackbox where apps can send data in order to be anonymised and aggregate to provide usage stats. Infrastructure workflow We have two environements, a dev one and a production. Both of them look like the following schema : On the developpement env, the 'cozy env' refers to our 'Alpha' VM. Service There is a service named aggregatorUsageEvent , running on a daily basis, sending pre-processed data to cozy. This service is responsible for parsing traced events store in database and send them to cozy. The service is configured to run every night at 01:00AM . Usage events This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Title Tech name target context startDate result trigger Cozy Dacc Name Changement d'action dans un challenge ActionChangeEvent Id de l'action Id du challenge en cours --- --- Chaque appui sur le bouton selectEcogesture dans le ActionCard navigation-action-daily Validation de la fin d'une action ActionEndEvent Id de l'ecogeste Id du challenge en cours Date de d\u00e9but de l'action --- Lors de l'appui sur le bouton de fin d'action event-duration Connexion d'un utilisateur ConnectionEvent --- Navigateur utilis\u00e9 --- Si c'est la premi\u00e8re connexion firstConnection est stock\u00e9 A chaque chargement de l'application connection-count-daily Connecteur Classique KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' en cas d'erreur de quelque type que ce soit (catch) konnector-event-daily Connecteur Oauth (enedis, GRDF) KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' dans le cas ou aucun accoun n'est cr\u00e9\u00e9 konnector-event-daily Refresh manuel du connecteur KonnectorRefreshEvent Slug du connecteur --- --- Success ou error. Le succ\u00e8s est set quand l'\u00e9tat du trigger est a 'done' Lors de l'appuie sur le bouton 'mettre a jour' konnector-event-daily Navigation utilisateur dans l'application NavigationEvent Nom de la page ( voir 1. en dessous ) --- --- --- --- navigation-count-daily Comparaison de consomation ConsumptionCompareEvent timestep in lowercase fluid type in lowercase --- --- --- navigation-action-daily Changement de pas de temps ConsumptionChangeTimeStepEvent timestep in lowercase fluid type --- --- --- navigation-action-daily Lancement d'un challenge ChallengeLaunchEvent challenge id --- --- --- Appuie sur le bouton de lancement de challenge dans le cas on la pop-up 'pas de fluid' ne s'affiche pas event-duration Title Tech name target context startDate result trigger Cozy Dacc Name Fin d'un challenge ChallengeEndEvent challenge id --- date de d\u00e9but du challenge --- Lors de la visualisation d'un challenge, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration D\u00e9but d'un duel DuelLaunchEvent duel id challenge id --- --- Appuie sur le bouton de lancement d'un duel event-duration Fin d'un duel DuelEndEvent duel id --- challenge start date 'win' or 'loss' Lors de la visualisation d'un duel, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration Fin d'un quiz QuizEndEvent Quiz id Challenge Id Quiz start date Resultat du quiz (de 0 a 5) Lors de la pop-up de r\u00e9sultat event-duration Fin d'une exploration ExplorationEndEvent exploration id challenge id exploration start date --- Lors de la pop-up de r\u00e9sultat event-duration Changement de choix d'action ActionChangeEvent action id current challenge id --- --- Lors du click sur le bouton d'acceptation de l'action navigation-action-daily Fin d'une action ActionEndEvent action id current challenge id action start date --- Lors du click sur le bouton de validation de la page ActionDone event-duration Compl\u00e9tion d'un nouveau profile ProfileSetEvent --- --- --- --- Lors de l'affichage de la page de f\u00e9licitation profileTypeFinished navigation-action-daily Consultation du nouveau bilan mensuel ReportFromEvent --- 'analysis' --- 1 Lorsque l'utilisateur consulte sa page analyse quand la notification est activ\u00e9e summary-subscription-monthly Tentatitve de connexion \u00e0 un connecteur (initialisation) KonnectorAttemptEvent Slug du connecteur --- --- 'success or error' Lorsque l'utilisateur clique sur le bouton de connexion. Lorsque la connexion est r\u00e9ussie, et que l'utilisateur clique sur OK dans la modale le result est pass\u00e9 \u00e0 'success' konnector-attempts-monthly Nom de la page, diff\u00e9rents cas existant Page target Trigger Consomation 'electricity', 'gas', 'eau', 'multifluid' Click sur un des fluids dans la bar navigation FAQ 'faq' Click sur la card de consultation CGU 'legalNotice' Click sur la card de Legal Notice Autres 'consumption' 'challenges' 'ecogestures' 'analysis' 'options' Click dans la navbar Indicators note All indicators are only sent if a user validate first version of CGU, the one containing dacc validation Monthly Indicators All monthly indicators call can be found after this comment on the code // Monthly events Indicator Trigger value consumption-variation-monthly Tous les mois si l'utilisateur a \u00e9t\u00e9 connect\u00e9 au moins une fois dans le mois La variation de consomation par type de fluide. Les param\u00e8tres diff\u00e9rents sont le type de profil ainsi que le nombre de mois entre la premi\u00e8re connexion de l'utilisateur et le moment o\u00f9 est remont\u00e9 l'indicateur (seniority) summary-subscription-monthly Tous les mois si un utilisateur a souscrit a la newsletter ou c'est d\u00e9sabonn\u00e9 1 si l'utilsteur est inscrit sinon 0 fluid-data-granularity-monthly Tous les mois sans condition 1 si l'utilisateur poss\u00e8de de la donn\u00e9e a la demi heure sur le mois. Sinon 0 connection-count-monthly Tous les mois Le nombre de jour unique de connexion sur le mois pr\u00e9c\u00e9dent. Sinon auncune connexion, 0 profile-count-monthly Tous les mois si le profil a \u00e9t\u00e9 compl\u00e9t\u00e9 au moins une fois Le nombre de fois ou le profile a \u00e9t\u00e9 compl\u00e9t\u00e9 konnector-attempts-monthly Tous les mois, le nombre de tentative de connexion pour connecter un connecteur la premi\u00e8re fois. Une fois la connexion r\u00e9ussie, l'indicateur remonte true dans le groupe \"success\". L'indicateur ne remonte ensuite plus pour cet utilisateur car il aura d\u00e9j\u00e0 r\u00e9ussi \u00e0 se connecter une premi\u00e8re fois. Le nombre total de tentatives Daily Indicators The daily process get all events of previous day and process them in the following indicators Indicator Trigger value connection-count-daily Tous les jours Nombre de connexion. Celle-ci sont cat\u00e9goris\u00e9 par type (mobile ou desktop), bas\u00e9 sur le navigateur de l'utilisateur. (les tablettes sont compt\u00e9es comme des mobiles) konnector-event-daily Tous les jours Nombre d'essai. Ils sont cat\u00e9goris\u00e9 par type de connecteur, refresh/success et le status (error ou success) konnector-connected-daily Tous les jours La valeur est 1. Les valeurs sont cat\u00e9goris\u00e9es par type de fluide (electricity / electricity:water ...) navigation-count-daily Tous les jours nombre de page visualis\u00e9 par type de page challenge-launch-daily Tous les jours Nombre de d\u00e9fis lanc\u00e9s lors d'un challenge session-duration Tous les jours Dur\u00e9e de la session en secondes navigation-action-daily Tous les jours Nombre d'action sur une page donn\u00e9e. Exemple sur la consomation on trace les changements de pas de temps sur chaque graph. event-duration Tous les jours Dur\u00e9e entre deux \u00e9v\u00e9nements: 1ere session et premier challenge / d\u00e9but de challenge et fin de challenge / d\u00e9but d'exploration et fin d'exploration / d\u00e9but d'action et fin d'action / d\u00e9but de duel et fin de duel quiz-stars Tous les jours Nombre d'\u00e9toiles obtenu a la fin d'un quiz Information sending Format All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. The structure to send is the following : { createdBy: string measureName: string startDate: string value: number | null group1?: object group2?: object group3?: object } with: createdBy : contains \"ecolyo\" value. startDate : used to defined the start date of the indicator value : contains a value relevant to the defined indicator (example: number of page viewed on a day). groups : contains all attributes defining a indicator. Please refer to indicators definition (https://stats.cozycloud.cc/question#eyJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjo0LCJxdWVyeSI6eyJzb3VyY2UtdGFibGUiOjh9LCJ0eXBlIjoicXVlcnkifSwiZGlzcGxheSI6InRhYmxlIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319) mesureName : contains one of the following value ENUM value CONNECTION_COUNT_DAILY connection-count-daily KONNECTOR_EVENT_DAILY konnector-event-daily KONNECTOR_CONNECTED_PER_DAY konnector-connected-daily NAVIGATION_COUNT_DAILY navigation-count-daily CHALLENGE_LAUNCH_EVENT_DAILY challenge-launch-daily CONSUMPTION_VARIATION_MONTHLY consumption-variation-monthly SESSION_DURATION session-duration NAVIGATION_ACTION_DAILY navigation-action-daily EVENT_DURATION event-duration QUIZ_STARS quiz-stars SUMMARY_SUBSCRIPTION_MONTHLY summary-subscription-monthly FLUID_DATA_GRANULARITY fluid-data-granularity-monthly CONNECTION_COUNT_MONTHLY connection-count-monthly PROFILE_COUNT_MONTHLY profile-count-monthly KONNECTOR_ATTEMPTS_MONTHLY konnector-attempts-monthly Environnements There is two remote doctypes pointing to two differents mode. dacc-dev is used on alpha. \"dacc\" : { \"type\" : \"cc.cozycloud.dacc\" , \"verbs\" : [ \"ALL\" ] }, \"dacc-dev\" : { \"type\" : \"cc.cozycloud.dacc.dev\" , \"verbs\" : [ \"ALL\" ] }, How to local test ? First you need to modify the service in order to be able to see data in local : Modify dacc URL in order to see data (ligne 67) await client . getStackClient () . fetchJSON ( 'POST' , environementService . isProduction () ? 'http://localhost:8081' : '/remote/cc.cozycloud.dacc.dev' , { data : JSON . stringify ( indicator ), } ) Remove date protection if you want to test monthly indicators (ligne 1100) if ( profile // && // DateTime.local() // .setZone('utc', { // keepLocalTime: true, // }) // .startOf('day').day === profile.monthlyAnalysisDate.day ) { Then you need to launch a script that will simulate dacc api's. This terminal will listen to incoming request cd ./scripts node server.js Then you are finally ready to test ! Just run the following : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\a ggregatorUsageEvents \\e colyo.js You must see sent indicators in the previously open terminal { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } How to add new indicator ? You have to reach cozy and discuss with them about new indicators. They will implement it for dacc-dev and dacc and you will be able to test it on alpha env. Remember you will need at least 5 data of each type to see it in metabase. Visualisation All the data aggregated in the dacc can be visualized with a Metabase website hosted by cozy (https://stats.cozycloud.cc/).","title":"Dacc"},{"location":"ecolyo/functionalities/dacc/#dacc","text":"What is DACC ? A cozy blackbox where apps can send data in order to be anonymised and aggregate to provide usage stats.","title":"DACC"},{"location":"ecolyo/functionalities/dacc/#infrastructure-workflow","text":"We have two environements, a dev one and a production. Both of them look like the following schema : On the developpement env, the 'cozy env' refers to our 'Alpha' VM.","title":"Infrastructure workflow"},{"location":"ecolyo/functionalities/dacc/#service","text":"There is a service named aggregatorUsageEvent , running on a daily basis, sending pre-processed data to cozy. This service is responsible for parsing traced events store in database and send them to cozy. The service is configured to run every night at 01:00AM .","title":"Service"},{"location":"ecolyo/functionalities/dacc/#usage-events","text":"This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Title Tech name target context startDate result trigger Cozy Dacc Name Changement d'action dans un challenge ActionChangeEvent Id de l'action Id du challenge en cours --- --- Chaque appui sur le bouton selectEcogesture dans le ActionCard navigation-action-daily Validation de la fin d'une action ActionEndEvent Id de l'ecogeste Id du challenge en cours Date de d\u00e9but de l'action --- Lors de l'appui sur le bouton de fin d'action event-duration Connexion d'un utilisateur ConnectionEvent --- Navigateur utilis\u00e9 --- Si c'est la premi\u00e8re connexion firstConnection est stock\u00e9 A chaque chargement de l'application connection-count-daily Connecteur Classique KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' en cas d'erreur de quelque type que ce soit (catch) konnector-event-daily Connecteur Oauth (enedis, GRDF) KonnectorConnectEvent Slug du connecteur --- --- Success ou error Le succ\u00e8s dans le cas ou on a la pop-up 'f\u00e9licitation', le 'error' dans le cas ou aucun accoun n'est cr\u00e9\u00e9 konnector-event-daily Refresh manuel du connecteur KonnectorRefreshEvent Slug du connecteur --- --- Success ou error. Le succ\u00e8s est set quand l'\u00e9tat du trigger est a 'done' Lors de l'appuie sur le bouton 'mettre a jour' konnector-event-daily Navigation utilisateur dans l'application NavigationEvent Nom de la page ( voir 1. en dessous ) --- --- --- --- navigation-count-daily Comparaison de consomation ConsumptionCompareEvent timestep in lowercase fluid type in lowercase --- --- --- navigation-action-daily Changement de pas de temps ConsumptionChangeTimeStepEvent timestep in lowercase fluid type --- --- --- navigation-action-daily Lancement d'un challenge ChallengeLaunchEvent challenge id --- --- --- Appuie sur le bouton de lancement de challenge dans le cas on la pop-up 'pas de fluid' ne s'affiche pas event-duration Title Tech name target context startDate result trigger Cozy Dacc Name Fin d'un challenge ChallengeEndEvent challenge id --- date de d\u00e9but du challenge --- Lors de la visualisation d'un challenge, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration D\u00e9but d'un duel DuelLaunchEvent duel id challenge id --- --- Appuie sur le bouton de lancement d'un duel event-duration Fin d'un duel DuelEndEvent duel id --- challenge start date 'win' or 'loss' Lors de la visualisation d'un duel, si le resultat de celui-ci est a 'fini' on enregistre l'\u00e9v\u00e9nement event-duration Fin d'un quiz QuizEndEvent Quiz id Challenge Id Quiz start date Resultat du quiz (de 0 a 5) Lors de la pop-up de r\u00e9sultat event-duration Fin d'une exploration ExplorationEndEvent exploration id challenge id exploration start date --- Lors de la pop-up de r\u00e9sultat event-duration Changement de choix d'action ActionChangeEvent action id current challenge id --- --- Lors du click sur le bouton d'acceptation de l'action navigation-action-daily Fin d'une action ActionEndEvent action id current challenge id action start date --- Lors du click sur le bouton de validation de la page ActionDone event-duration Compl\u00e9tion d'un nouveau profile ProfileSetEvent --- --- --- --- Lors de l'affichage de la page de f\u00e9licitation profileTypeFinished navigation-action-daily Consultation du nouveau bilan mensuel ReportFromEvent --- 'analysis' --- 1 Lorsque l'utilisateur consulte sa page analyse quand la notification est activ\u00e9e summary-subscription-monthly Tentatitve de connexion \u00e0 un connecteur (initialisation) KonnectorAttemptEvent Slug du connecteur --- --- 'success or error' Lorsque l'utilisateur clique sur le bouton de connexion. Lorsque la connexion est r\u00e9ussie, et que l'utilisateur clique sur OK dans la modale le result est pass\u00e9 \u00e0 'success' konnector-attempts-monthly Nom de la page, diff\u00e9rents cas existant Page target Trigger Consomation 'electricity', 'gas', 'eau', 'multifluid' Click sur un des fluids dans la bar navigation FAQ 'faq' Click sur la card de consultation CGU 'legalNotice' Click sur la card de Legal Notice Autres 'consumption' 'challenges' 'ecogestures' 'analysis' 'options' Click dans la navbar","title":"Usage events"},{"location":"ecolyo/functionalities/dacc/#indicators","text":"note All indicators are only sent if a user validate first version of CGU, the one containing dacc validation","title":"Indicators"},{"location":"ecolyo/functionalities/dacc/#monthly-indicators","text":"All monthly indicators call can be found after this comment on the code // Monthly events Indicator Trigger value consumption-variation-monthly Tous les mois si l'utilisateur a \u00e9t\u00e9 connect\u00e9 au moins une fois dans le mois La variation de consomation par type de fluide. Les param\u00e8tres diff\u00e9rents sont le type de profil ainsi que le nombre de mois entre la premi\u00e8re connexion de l'utilisateur et le moment o\u00f9 est remont\u00e9 l'indicateur (seniority) summary-subscription-monthly Tous les mois si un utilisateur a souscrit a la newsletter ou c'est d\u00e9sabonn\u00e9 1 si l'utilsteur est inscrit sinon 0 fluid-data-granularity-monthly Tous les mois sans condition 1 si l'utilisateur poss\u00e8de de la donn\u00e9e a la demi heure sur le mois. Sinon 0 connection-count-monthly Tous les mois Le nombre de jour unique de connexion sur le mois pr\u00e9c\u00e9dent. Sinon auncune connexion, 0 profile-count-monthly Tous les mois si le profil a \u00e9t\u00e9 compl\u00e9t\u00e9 au moins une fois Le nombre de fois ou le profile a \u00e9t\u00e9 compl\u00e9t\u00e9 konnector-attempts-monthly Tous les mois, le nombre de tentative de connexion pour connecter un connecteur la premi\u00e8re fois. Une fois la connexion r\u00e9ussie, l'indicateur remonte true dans le groupe \"success\". L'indicateur ne remonte ensuite plus pour cet utilisateur car il aura d\u00e9j\u00e0 r\u00e9ussi \u00e0 se connecter une premi\u00e8re fois. Le nombre total de tentatives","title":"Monthly Indicators"},{"location":"ecolyo/functionalities/dacc/#daily-indicators","text":"The daily process get all events of previous day and process them in the following indicators Indicator Trigger value connection-count-daily Tous les jours Nombre de connexion. Celle-ci sont cat\u00e9goris\u00e9 par type (mobile ou desktop), bas\u00e9 sur le navigateur de l'utilisateur. (les tablettes sont compt\u00e9es comme des mobiles) konnector-event-daily Tous les jours Nombre d'essai. Ils sont cat\u00e9goris\u00e9 par type de connecteur, refresh/success et le status (error ou success) konnector-connected-daily Tous les jours La valeur est 1. Les valeurs sont cat\u00e9goris\u00e9es par type de fluide (electricity / electricity:water ...) navigation-count-daily Tous les jours nombre de page visualis\u00e9 par type de page challenge-launch-daily Tous les jours Nombre de d\u00e9fis lanc\u00e9s lors d'un challenge session-duration Tous les jours Dur\u00e9e de la session en secondes navigation-action-daily Tous les jours Nombre d'action sur une page donn\u00e9e. Exemple sur la consomation on trace les changements de pas de temps sur chaque graph. event-duration Tous les jours Dur\u00e9e entre deux \u00e9v\u00e9nements: 1ere session et premier challenge / d\u00e9but de challenge et fin de challenge / d\u00e9but d'exploration et fin d'exploration / d\u00e9but d'action et fin d'action / d\u00e9but de duel et fin de duel quiz-stars Tous les jours Nombre d'\u00e9toiles obtenu a la fin d'un quiz","title":"Daily Indicators"},{"location":"ecolyo/functionalities/dacc/#information-sending","text":"","title":"Information sending"},{"location":"ecolyo/functionalities/dacc/#format","text":"All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. The structure to send is the following : { createdBy: string measureName: string startDate: string value: number | null group1?: object group2?: object group3?: object } with: createdBy : contains \"ecolyo\" value. startDate : used to defined the start date of the indicator value : contains a value relevant to the defined indicator (example: number of page viewed on a day). groups : contains all attributes defining a indicator. Please refer to indicators definition (https://stats.cozycloud.cc/question#eyJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjo0LCJxdWVyeSI6eyJzb3VyY2UtdGFibGUiOjh9LCJ0eXBlIjoicXVlcnkifSwiZGlzcGxheSI6InRhYmxlIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319) mesureName : contains one of the following value ENUM value CONNECTION_COUNT_DAILY connection-count-daily KONNECTOR_EVENT_DAILY konnector-event-daily KONNECTOR_CONNECTED_PER_DAY konnector-connected-daily NAVIGATION_COUNT_DAILY navigation-count-daily CHALLENGE_LAUNCH_EVENT_DAILY challenge-launch-daily CONSUMPTION_VARIATION_MONTHLY consumption-variation-monthly SESSION_DURATION session-duration NAVIGATION_ACTION_DAILY navigation-action-daily EVENT_DURATION event-duration QUIZ_STARS quiz-stars SUMMARY_SUBSCRIPTION_MONTHLY summary-subscription-monthly FLUID_DATA_GRANULARITY fluid-data-granularity-monthly CONNECTION_COUNT_MONTHLY connection-count-monthly PROFILE_COUNT_MONTHLY profile-count-monthly KONNECTOR_ATTEMPTS_MONTHLY konnector-attempts-monthly","title":"Format"},{"location":"ecolyo/functionalities/dacc/#environnements","text":"There is two remote doctypes pointing to two differents mode. dacc-dev is used on alpha. \"dacc\" : { \"type\" : \"cc.cozycloud.dacc\" , \"verbs\" : [ \"ALL\" ] }, \"dacc-dev\" : { \"type\" : \"cc.cozycloud.dacc.dev\" , \"verbs\" : [ \"ALL\" ] },","title":"Environnements"},{"location":"ecolyo/functionalities/dacc/#how-to-local-test","text":"First you need to modify the service in order to be able to see data in local : Modify dacc URL in order to see data (ligne 67) await client . getStackClient () . fetchJSON ( 'POST' , environementService . isProduction () ? 'http://localhost:8081' : '/remote/cc.cozycloud.dacc.dev' , { data : JSON . stringify ( indicator ), } ) Remove date protection if you want to test monthly indicators (ligne 1100) if ( profile // && // DateTime.local() // .setZone('utc', { // keepLocalTime: true, // }) // .startOf('day').day === profile.monthlyAnalysisDate.day ) { Then you need to launch a script that will simulate dacc api's. This terminal will listen to incoming request cd ./scripts node server.js Then you are finally ready to test ! Just run the following : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\a ggregatorUsageEvents \\e colyo.js You must see sent indicators in the previously open terminal { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' } { da ta : ' { \"createdBy\" : \"ecolyo\" , \"measureName\" : \"connection-count-monthly\" , \"startDate\" : \"2021-12-09\" , \"value\" : 3 } ' }","title":"How to local test ?"},{"location":"ecolyo/functionalities/dacc/#how-to-add-new-indicator","text":"You have to reach cozy and discuss with them about new indicators. They will implement it for dacc-dev and dacc and you will be able to test it on alpha env. Remember you will need at least 5 data of each type to see it in metabase.","title":"How to add new indicator ?"},{"location":"ecolyo/functionalities/dacc/#visualisation","text":"All the data aggregated in the dacc can be visualized with a Metabase website hosted by cozy (https://stats.cozycloud.cc/).","title":"Visualisation"},{"location":"ecolyo/functionalities/ecogesture/","text":"Ecogesture Description An ecogesture is a gesture that encourages user to take action for reduce their own consumption. It includes different information such as icon, name, long and short description, its efficiency on the consumption and which fluid is affected. Also, an ecogesture can be used for an action challenge. Model Ecogesture { id: string shortName: string longName: string longDescription: string usage: Usage fluidTypes: FluidType[] impactLevel: number efficiency: number difficulty: number room: Room[] season: Season equipment: boolean equipmentType: EquipmentType[] equipmentInstallation: boolean investment: string | null action: boolean actionName: string | null actionDuration: number objective: boolean doing: boolean viewedInSelection: boolean } Ecogestures screen This screen is divided in 3 tabs : - ALL : display the full list of ecogestures. User can filter ecogesture by usage. - DOING : display the list of doing ecogestures. User can filter ecogesture by usage. - OBJECTIVES : display the list of objectives ecogestures. User can filter ecogesture by usage. RULES By default the ALL tab is selected. If user click on an ecogesture, he will see more information about it and will be able to choose manually if it is doing AND/OR objective The back arrow button on a single ecogesture returns to the tab he came through. Ecogesture Status An ecogesture can have a status according the user's choice, it can be doing and/or objective which allows the user to consult them in the related tabs in the ecogesture page. On it is selected by the user in the tinder-like tunnel, the viewedInSelection key is set to true, so the user won't see it again in its selection. Profile Ecogesture The first time the user consults the ecogesture page, he will be prompted to start selecting his custom ecogestures. - If he refuses, I will still be able to access this functionnality by clicking on the \"Select\" button on the tabs 'Doing' and 'Objectives' while they are still empty. - If he starts select ecogestures on his own by the tab 'All' and fill both 'objective' and 'doing' sections, he won't be able to access the form and selection as described in the next parts. Model ProfileEcogesture { heating: IndividualOrCollective warmingFluid: WarmingType | null hotWater: IndividualOrCollective equipments: EquipmentType[] } Ecogesture Form The form is compose in 2 parts : - The first is made of question concerning his heating fluid and type (individual or collective), and his hotWater type. - The second part asks the user to pick the equipment he has. If the user has completed his profileType, he won't see the first part as it is automatically completed with the information he filled in his profileType The first part filters his custom list by Usages ECS and HEATING The second part filters his custom list by Equipments Ecogesture Selection Once user has completed his profile ecogesture through the form, he has the possibility to enter the ecogesture selection (tinder-like) - A list of custom ecogesture is made according to his profile - User will cross this list 10 by 10, and has to choose if it is 'doing' 'objective' or 'not interested Important Rules If uses refuses to do the selection for now, he will be reminded to do it in the 'doing' and 'objective' tabs, and a continue button will show User can go back and correct his answer at any time User can stop the process at any time, hist answer will be saved ad the next time he will open the selection, a new stack of 10 ecogesture is made (for example, user stops at 4/10, the next time he opens the selection it will be 4/14) If user chooses to select manually an ecogesture outside of the selection tunnel (through the 'all' tab), this ecogesture will be removed from the list it was existing in it. If user choses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), these ecogestures won't be purposes again in the selection tunnel. User can't use the back arrow on the first ecogesture of selection list Once the whole process is done, the user has no possibility to do it again through the tinder-like selection, but he can still edit his ecogestures manually from the various tabs. Case ecogesture usage is heating We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual heating which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual heating which use gas fluid. Case ecogesture usage is ECS ECS = Eau chaude sanitaire We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual hot water which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual hot water which use gas fluid. Case ecogesture usage is Cooking We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an electricity fluid for cooking. OR the ecogesture has gas fluid and profile type has an gas fluid for cooking. Case ecogesture usage is cold water We will display the ecogesture if the profile type has individual cold water. Case ecogesture usage is specific electricity We will display the ecogesture. Case ecogesture usage is air conditioning We will NOT display the ecogesture.","title":"Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture","text":"","title":"Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#description","text":"An ecogesture is a gesture that encourages user to take action for reduce their own consumption. It includes different information such as icon, name, long and short description, its efficiency on the consumption and which fluid is affected. Also, an ecogesture can be used for an action challenge.","title":"Description"},{"location":"ecolyo/functionalities/ecogesture/#model","text":"Ecogesture { id: string shortName: string longName: string longDescription: string usage: Usage fluidTypes: FluidType[] impactLevel: number efficiency: number difficulty: number room: Room[] season: Season equipment: boolean equipmentType: EquipmentType[] equipmentInstallation: boolean investment: string | null action: boolean actionName: string | null actionDuration: number objective: boolean doing: boolean viewedInSelection: boolean }","title":"Model"},{"location":"ecolyo/functionalities/ecogesture/#ecogestures-screen","text":"This screen is divided in 3 tabs : - ALL : display the full list of ecogestures. User can filter ecogesture by usage. - DOING : display the list of doing ecogestures. User can filter ecogesture by usage. - OBJECTIVES : display the list of objectives ecogestures. User can filter ecogesture by usage.","title":"Ecogestures screen"},{"location":"ecolyo/functionalities/ecogesture/#rules","text":"By default the ALL tab is selected. If user click on an ecogesture, he will see more information about it and will be able to choose manually if it is doing AND/OR objective The back arrow button on a single ecogesture returns to the tab he came through.","title":"RULES"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-status","text":"An ecogesture can have a status according the user's choice, it can be doing and/or objective which allows the user to consult them in the related tabs in the ecogesture page. On it is selected by the user in the tinder-like tunnel, the viewedInSelection key is set to true, so the user won't see it again in its selection.","title":"Ecogesture Status"},{"location":"ecolyo/functionalities/ecogesture/#profile-ecogesture","text":"The first time the user consults the ecogesture page, he will be prompted to start selecting his custom ecogestures. - If he refuses, I will still be able to access this functionnality by clicking on the \"Select\" button on the tabs 'Doing' and 'Objectives' while they are still empty. - If he starts select ecogestures on his own by the tab 'All' and fill both 'objective' and 'doing' sections, he won't be able to access the form and selection as described in the next parts.","title":"Profile Ecogesture"},{"location":"ecolyo/functionalities/ecogesture/#model_1","text":"ProfileEcogesture { heating: IndividualOrCollective warmingFluid: WarmingType | null hotWater: IndividualOrCollective equipments: EquipmentType[] }","title":"Model"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-form","text":"The form is compose in 2 parts : - The first is made of question concerning his heating fluid and type (individual or collective), and his hotWater type. - The second part asks the user to pick the equipment he has. If the user has completed his profileType, he won't see the first part as it is automatically completed with the information he filled in his profileType The first part filters his custom list by Usages ECS and HEATING The second part filters his custom list by Equipments","title":"Ecogesture Form"},{"location":"ecolyo/functionalities/ecogesture/#ecogesture-selection","text":"Once user has completed his profile ecogesture through the form, he has the possibility to enter the ecogesture selection (tinder-like) - A list of custom ecogesture is made according to his profile - User will cross this list 10 by 10, and has to choose if it is 'doing' 'objective' or 'not interested","title":"Ecogesture Selection"},{"location":"ecolyo/functionalities/ecogesture/#important-rules","text":"If uses refuses to do the selection for now, he will be reminded to do it in the 'doing' and 'objective' tabs, and a continue button will show User can go back and correct his answer at any time User can stop the process at any time, hist answer will be saved ad the next time he will open the selection, a new stack of 10 ecogesture is made (for example, user stops at 4/10, the next time he opens the selection it will be 4/14) If user chooses to select manually an ecogesture outside of the selection tunnel (through the 'all' tab), this ecogesture will be removed from the list it was existing in it. If user choses to remove manually an ecogesture outside of the selection tunnel (through the 'doing' and 'objective' tab), these ecogestures won't be purposes again in the selection tunnel. User can't use the back arrow on the first ecogesture of selection list Once the whole process is done, the user has no possibility to do it again through the tinder-like selection, but he can still edit his ecogestures manually from the various tabs.","title":"Important Rules"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-heating","text":"We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual heating which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual heating which use gas fluid.","title":"Case ecogesture usage is heating"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-ecs","text":"ECS = Eau chaude sanitaire We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an individual hot water which use electricity fluid. OR the ecogesture has gas fluid and profile type has an individual hot water which use gas fluid.","title":"Case ecogesture usage is ECS"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-cooking","text":"We will display the ecogesture if: the ecogesture has electricity fluid and profile type has an electricity fluid for cooking. OR the ecogesture has gas fluid and profile type has an gas fluid for cooking.","title":"Case ecogesture usage is Cooking"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-cold-water","text":"We will display the ecogesture if the profile type has individual cold water.","title":"Case ecogesture usage is cold water"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-specific-electricity","text":"We will display the ecogesture.","title":"Case ecogesture usage is specific electricity"},{"location":"ecolyo/functionalities/ecogesture/#case-ecogesture-usage-is-air-conditioning","text":"We will NOT display the ecogesture.","title":"Case ecogesture usage is air conditioning"},{"location":"ecolyo/functionalities/feedback/","text":"Feedback Users can send a feedback in the application, the feedback's receiver is defined in the FeedbackModal component Add mail attachments The user has the possibility to add an image to a feedback. The email information are created in the sendEmail function and the mailData respects this scheme : const mailData = { mode : \"from\" , to : [{ name : \"Support\" , email : \"receiver-email\" }], subject : \"Your subject\" , parts : [{ type : \"text/plain\" , body : mailContent }], attachments : [{ filename : \"test.png\" , content : \"base64file\" }], }; It is important that your file is sent base64 encoded to the sendmail job and with the data...base64 headers removed, otherwise it will be unreadable. In order to do this, we use a reader to read the file as Data URL reader . readAsDataURL ( file ); and then apply to the result so we send only the encoded part without its headers. split ( \",\" )[ 1 ];","title":"Feedback"},{"location":"ecolyo/functionalities/feedback/#feedback","text":"Users can send a feedback in the application, the feedback's receiver is defined in the FeedbackModal component","title":"Feedback"},{"location":"ecolyo/functionalities/feedback/#add-mail-attachments","text":"The user has the possibility to add an image to a feedback. The email information are created in the sendEmail function and the mailData respects this scheme : const mailData = { mode : \"from\" , to : [{ name : \"Support\" , email : \"receiver-email\" }], subject : \"Your subject\" , parts : [{ type : \"text/plain\" , body : mailContent }], attachments : [{ filename : \"test.png\" , content : \"base64file\" }], }; It is important that your file is sent base64 encoded to the sendmail job and with the data...base64 headers removed, otherwise it will be unreadable. In order to do this, we use a reader to read the file as Data URL reader . readAsDataURL ( file ); and then apply to the result so we send only the encoded part without its headers. split ( \",\" )[ 1 ];","title":"Add mail attachments"},{"location":"ecolyo/functionalities/initialization/","text":"This section explains how to handle data storage. We handle data storage according to the following process : The folder /src/db contains all the JSON entities that are directly stored in the couchDB during the initialization process that is executed in the splash screen. They are stored under their related doctype. Initialization and Updating During the initialization process, we store a hash for each dataEntity that is likely to be changed or updated. The hash is stored in the userProfile. [ { \"ecogestureHash\" : \"\" , \"challengeHash\" : \"\" , \"quizHash\" : \"\" , \"explorationHash\" : \"\" , \"duelHash\" : \"\" , \"isFirstConnection\" : true , \"haveSeenFavoriteModal\" : false , \"haveSeenOldFluidModal\" : false , \"haveSeenLastReport\" : true , \"sendReportNotification\" : false , \"monthlyReportDate\" : \"0000-01-01T00:00:00.000Z\" } ] This way, once the initialization is launched, we compare the hash we have in the current userProfile with the one generated from the entity located in /db folder, and if they are different we update the couchDB with the new data. In order to handle this process, each entity that is likely to change has a function that takes the current hash in entry, and execute the following process : creates a hash from the related entity file (for example EcogestureData.json ) get the entities from the database if there is no entity stored, populates the related doctype (for this example ECOGESTURE_DOCTYPE ) for each item stored in the entity file compare the number of entries created in the doctype with the number of item in the entity file if the previous hash and the new hash are different, delete all entries in the doctype and populates with the items stored in the entity file Functions used to init or update the hash : Function initEcogesture(hash: string) initChallengeEntity(hash: string) initDuelEntity(hash: string) initQuizEntity(hash: string) initExplorationEntity(hash: string) Exception for ecogestures When we update the ecogesture list in ecogestureData.json , we also get the previous existing list to transfer the ecogesture status (doing and/or objective) to the updated list. dataEntity vs userData In the project, you'll see two versions for the same data. The dataEntity (quizEntity, challengeEntity, ...) is the data stored in the db folder and in the couchDB. These data are only edited in the couchDB when we update a challenge/quiz/duel or add a new one. The userData (userChallenge, userQuiz...) is created from the entity and extended with user's data, such as his progress, his consumption data, goals, fails etc. Using this 2 structures allows us to keep user's datas when we'll update the application, by editing just the entities. Relationships Relationships is a functionality made by cozy, they are built with the name of the relation, containing a \"data\" object, itself containing the id of the related item and its doctype \"_type\". Using this allows us to reduce the size of the stored items and increase readability. Relations are set as HasOne relationships for Quiz and Duel because there is only one quiz and one duel for Challenge. Thus, we use a HasMany relation for the Exploration , because one challenge can have several exploration in order the handle the specific cases of fluid-based explorations. You can see more about relationships on cozy documentation . \"relationships\" : { \"quiz\" : { \"data\" : { \"_id\" : \"QUIZ001\" , \"_type\" : \"com.grandlyon.ecolyo.quiz\" } }, \"duel\" : { \"data\" : { \"_id\" : \"DUEL001\" , \"_type\" : \"com.grandlyon.ecolyo.duel\" } }, \"exploration\" : { \"data\" : [ { \"_id\" : \"EXPLORATION001\" , \"_type\" : \"com.grandlyon.ecolyo.exploration\" } ] } } UserData creation We create a userData and store it in the couchDB under the doctype userData name ' com.grandlyon.ecolyo.userDataName'. During this process, the objects related to the dataEntity will be be converted to an user version which contains information about the user(example: user progress, the fluids connected and so on). To illustrate this, let's show an example of the conversion of duelEntity to UserDuel : DuelEntity { id: string title: string description: string duration: Duration } Becomes : UserDuel { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: DateTime | null fluidTypes: FluidType[] userConsumption: number } Since we use the Luxon library for DateTimes, we need to have an intermediate interface for the UserDuel. Indeed, the database doesn't know the DateTime type, so when we query a UserDuel, its startDate property is a string and not a DateTime . The solve this and avoid Typescript errors, we created the following interface : UserDuelEntity { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: string | null fluidTypes: FluidType[] userConsumption: number } Data managment schema Loader The initialization process displays progression steps in the splash screen so the user can see what is happening while it is loading. Each initialization function set an error if it fails, which is shown on the Slpash error screnn. Available loading steps are the followings : ```` MIGRATION = 0, CONSENT = 1, PROFILE = 2, ECOGESTURE = 3, CHALLENGES = 4, PRICES = 5, CONSOS = 6, ``` Possible errors are the followings : MIGRATION_ERROR = 'migration_error', CONSENT_ERROR = 'consent_error', PROFILE_ERROR = 'profile_error', PROFILETYPE_ERROR = 'profileType_error', ECOGESTURE_ERROR = 'ecogesture_error', CHALLENGES_ERROR = 'challenges_error', ANALYSIS_ERROR = 'analysis_error', INDEX_ERROR = 'index_error', PRICES_ERROR = 'prices_error', CONSOS_ERROR = 'consos_error', PARTNERS_ERROR = 'partners_error', UNKNOWN_ERROR = 'unknown_error',","title":"Initialization"},{"location":"ecolyo/functionalities/initialization/#initialization-and-updating","text":"During the initialization process, we store a hash for each dataEntity that is likely to be changed or updated. The hash is stored in the userProfile. [ { \"ecogestureHash\" : \"\" , \"challengeHash\" : \"\" , \"quizHash\" : \"\" , \"explorationHash\" : \"\" , \"duelHash\" : \"\" , \"isFirstConnection\" : true , \"haveSeenFavoriteModal\" : false , \"haveSeenOldFluidModal\" : false , \"haveSeenLastReport\" : true , \"sendReportNotification\" : false , \"monthlyReportDate\" : \"0000-01-01T00:00:00.000Z\" } ] This way, once the initialization is launched, we compare the hash we have in the current userProfile with the one generated from the entity located in /db folder, and if they are different we update the couchDB with the new data. In order to handle this process, each entity that is likely to change has a function that takes the current hash in entry, and execute the following process : creates a hash from the related entity file (for example EcogestureData.json ) get the entities from the database if there is no entity stored, populates the related doctype (for this example ECOGESTURE_DOCTYPE ) for each item stored in the entity file compare the number of entries created in the doctype with the number of item in the entity file if the previous hash and the new hash are different, delete all entries in the doctype and populates with the items stored in the entity file Functions used to init or update the hash : Function initEcogesture(hash: string) initChallengeEntity(hash: string) initDuelEntity(hash: string) initQuizEntity(hash: string) initExplorationEntity(hash: string) Exception for ecogestures When we update the ecogesture list in ecogestureData.json , we also get the previous existing list to transfer the ecogesture status (doing and/or objective) to the updated list.","title":"Initialization and Updating"},{"location":"ecolyo/functionalities/initialization/#dataentity-vs-userdata","text":"In the project, you'll see two versions for the same data. The dataEntity (quizEntity, challengeEntity, ...) is the data stored in the db folder and in the couchDB. These data are only edited in the couchDB when we update a challenge/quiz/duel or add a new one. The userData (userChallenge, userQuiz...) is created from the entity and extended with user's data, such as his progress, his consumption data, goals, fails etc. Using this 2 structures allows us to keep user's datas when we'll update the application, by editing just the entities.","title":"dataEntity vs userData"},{"location":"ecolyo/functionalities/initialization/#relationships","text":"Relationships is a functionality made by cozy, they are built with the name of the relation, containing a \"data\" object, itself containing the id of the related item and its doctype \"_type\". Using this allows us to reduce the size of the stored items and increase readability. Relations are set as HasOne relationships for Quiz and Duel because there is only one quiz and one duel for Challenge. Thus, we use a HasMany relation for the Exploration , because one challenge can have several exploration in order the handle the specific cases of fluid-based explorations. You can see more about relationships on cozy documentation . \"relationships\" : { \"quiz\" : { \"data\" : { \"_id\" : \"QUIZ001\" , \"_type\" : \"com.grandlyon.ecolyo.quiz\" } }, \"duel\" : { \"data\" : { \"_id\" : \"DUEL001\" , \"_type\" : \"com.grandlyon.ecolyo.duel\" } }, \"exploration\" : { \"data\" : [ { \"_id\" : \"EXPLORATION001\" , \"_type\" : \"com.grandlyon.ecolyo.exploration\" } ] } }","title":"Relationships"},{"location":"ecolyo/functionalities/initialization/#userdata-creation","text":"We create a userData and store it in the couchDB under the doctype userData name ' com.grandlyon.ecolyo.userDataName'. During this process, the objects related to the dataEntity will be be converted to an user version which contains information about the user(example: user progress, the fluids connected and so on). To illustrate this, let's show an example of the conversion of duelEntity to UserDuel : DuelEntity { id: string title: string description: string duration: Duration } Becomes : UserDuel { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: DateTime | null fluidTypes: FluidType[] userConsumption: number } Since we use the Luxon library for DateTimes, we need to have an intermediate interface for the UserDuel. Indeed, the database doesn't know the DateTime type, so when we query a UserDuel, its startDate property is a string and not a DateTime . The solve this and avoid Typescript errors, we created the following interface : UserDuelEntity { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: string | null fluidTypes: FluidType[] userConsumption: number }","title":"UserData creation"},{"location":"ecolyo/functionalities/initialization/#data-managment-schema","text":"","title":"Data managment schema"},{"location":"ecolyo/functionalities/initialization/#loader","text":"The initialization process displays progression steps in the splash screen so the user can see what is happening while it is loading. Each initialization function set an error if it fails, which is shown on the Slpash error screnn. Available loading steps are the followings : ```` MIGRATION = 0, CONSENT = 1, PROFILE = 2, ECOGESTURE = 3, CHALLENGES = 4, PRICES = 5, CONSOS = 6, ``` Possible errors are the followings : MIGRATION_ERROR = 'migration_error', CONSENT_ERROR = 'consent_error', PROFILE_ERROR = 'profile_error', PROFILETYPE_ERROR = 'profileType_error', ECOGESTURE_ERROR = 'ecogesture_error', CHALLENGES_ERROR = 'challenges_error', ANALYSIS_ERROR = 'analysis_error', INDEX_ERROR = 'index_error', PRICES_ERROR = 'prices_error', CONSOS_ERROR = 'consos_error', PARTNERS_ERROR = 'partners_error', UNKNOWN_ERROR = 'unknown_error',","title":"Loader"},{"location":"ecolyo/functionalities/onboarding/","text":"This section explains the way we handle onboarding the application. Description When the user connects for the first time to Ecolyo, onboarding screens will be displayed. First connection The first connection is define by the isFirstConnection boolean contains in the profile doctype. GCU screen First of all, we display the GCU screen, which allows user to read the General Condition of Use and the Legal Notive. The user should consent to all the terms to go further in the application. About terms More details are available on the (term section)[/ecolyo/functionalities/terms.md]. Welcome modal After GCU screen we display a welcome modal to inform user about further steps needed to use Ecolyo (connection to partners to retrieve the data, ...). We store in user's profile a boolean onboarding.isWelcomeSeen that allows the app to know is the modal has already be seen. If the modal has been seen we will never display it again. When user close this modal, the welcome mail is sent to the user.","title":"Onboarding"},{"location":"ecolyo/functionalities/onboarding/#description","text":"When the user connects for the first time to Ecolyo, onboarding screens will be displayed. First connection The first connection is define by the isFirstConnection boolean contains in the profile doctype.","title":"Description"},{"location":"ecolyo/functionalities/onboarding/#gcu-screen","text":"First of all, we display the GCU screen, which allows user to read the General Condition of Use and the Legal Notive. The user should consent to all the terms to go further in the application. About terms More details are available on the (term section)[/ecolyo/functionalities/terms.md].","title":"GCU screen"},{"location":"ecolyo/functionalities/onboarding/#welcome-modal","text":"After GCU screen we display a welcome modal to inform user about further steps needed to use Ecolyo (connection to partners to retrieve the data, ...). We store in user's profile a boolean onboarding.isWelcomeSeen that allows the app to know is the modal has already be seen. If the modal has been seen we will never display it again. When user close this modal, the welcome mail is sent to the user.","title":"Welcome modal"},{"location":"ecolyo/functionalities/prices_calculation/","text":"Price Calculation This section explains the price calculation process. Description Since version 1.6.0 of the app, we have a database storing fluid prices evolution sincre 2012 for the following fluids : * Elecricity * Gas Before this version, the app was applying a hard coded price for each fluid without taking care of the time period. Now, there is a service running every night that process fresh data in order to apply the current price to this data, but also apply the most relevant price for a fluid doctype. Service Process The Cozy service responsible for price calculation is fluidsPrices . You can find the full logic in the following diagram : This service is running every night at 02:00 AM. note You might observe some price miscalculation if data from konnector is collect after the service runtime. Because of the hard code price, which is the current price, the user should not see any difference. Init A migration job has been setup to init the database with json data store inside the app. This job should be run once and will init electricy and gas prices. New price In case of price update the following procedure must be done : * Create a migration for adding new prices * Update hard coded price inside app in order to maintain fallback calculation * Verify full service calculation with new data * Verify calculation with existing data note The service does not handle change during a month because the case does not exist anymore for Enedis and Grdf. Prices Data We store in databse a collection of prices with the following info : * StartDate * EndDate * fluidType * Price The EndDate is set to null if it's the current fluid price. App Price display The app can handle the new price calculation and also keep the old calculation system. Regular display If there is a price on the doctype we want to process, it will be use for display and calculation ( see analysis functionality). Fallback The app take the hard code price for a given fluid and apply it to a load. This allow the app to handle prices in any case. How to test service ? In a shell run a build and test service with le following command line : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\m onthlyReport \\e colyo.js Evolutions We might consider a more dynamic process for fallback price calculation in the future: * Get last price for a given price in database * Use it to calculate value instead of the hard coded one * Use it in all info pop-in for user information","title":"Price Calculation"},{"location":"ecolyo/functionalities/prices_calculation/#price-calculation","text":"This section explains the price calculation process.","title":"Price Calculation"},{"location":"ecolyo/functionalities/prices_calculation/#description","text":"Since version 1.6.0 of the app, we have a database storing fluid prices evolution sincre 2012 for the following fluids : * Elecricity * Gas Before this version, the app was applying a hard coded price for each fluid without taking care of the time period. Now, there is a service running every night that process fresh data in order to apply the current price to this data, but also apply the most relevant price for a fluid doctype.","title":"Description"},{"location":"ecolyo/functionalities/prices_calculation/#service","text":"","title":"Service"},{"location":"ecolyo/functionalities/prices_calculation/#process","text":"The Cozy service responsible for price calculation is fluidsPrices . You can find the full logic in the following diagram : This service is running every night at 02:00 AM. note You might observe some price miscalculation if data from konnector is collect after the service runtime. Because of the hard code price, which is the current price, the user should not see any difference.","title":"Process"},{"location":"ecolyo/functionalities/prices_calculation/#init","text":"A migration job has been setup to init the database with json data store inside the app. This job should be run once and will init electricy and gas prices.","title":"Init"},{"location":"ecolyo/functionalities/prices_calculation/#new-price","text":"In case of price update the following procedure must be done : * Create a migration for adding new prices * Update hard coded price inside app in order to maintain fallback calculation * Verify full service calculation with new data * Verify calculation with existing data note The service does not handle change during a month because the case does not exist anymore for Enedis and Grdf.","title":"New price"},{"location":"ecolyo/functionalities/prices_calculation/#prices-data","text":"We store in databse a collection of prices with the following info : * StartDate * EndDate * fluidType * Price The EndDate is set to null if it's the current fluid price.","title":"Prices Data"},{"location":"ecolyo/functionalities/prices_calculation/#app-price-display","text":"The app can handle the new price calculation and also keep the old calculation system.","title":"App Price display"},{"location":"ecolyo/functionalities/prices_calculation/#regular-display","text":"If there is a price on the doctype we want to process, it will be use for display and calculation ( see analysis functionality).","title":"Regular display"},{"location":"ecolyo/functionalities/prices_calculation/#fallback","text":"The app take the hard code price for a given fluid and apply it to a load. This allow the app to handle prices in any case.","title":"Fallback"},{"location":"ecolyo/functionalities/prices_calculation/#how-to-test-service","text":"In a shell run a build and test service with le following command line : yarn build-dev:browser ; yarn run cozy-konnector-dev -m . \\m anifest.webapp . \\b uild \\s ervices \\m onthlyReport \\e colyo.js","title":"How to test service ?"},{"location":"ecolyo/functionalities/prices_calculation/#evolutions","text":"We might consider a more dynamic process for fallback price calculation in the future: * Get last price for a given price in database * Use it to calculate value instead of the hard coded one * Use it in all info pop-in for user information","title":"Evolutions"},{"location":"ecolyo/functionalities/profile_type/","text":"This section explains the profileType creation process in order to make different comparisons between the actual user's consumption and its profile type. Profile type data The profileType data are stored in the profile doctype and includes the following information : { housingType: HousingType constructionYear: ConstructionYear area: string occupantsNumber: number outsideFacingWalls: OutsideFacingWalls floor: Floor heating: IndividualOrCollective coldWater: IndividualOrCollective hotWater: IndividualOrCollective individualInsulationWork: IndividualInsulationWork[] hasInstalledVentilation: ThreeChoicesAnswer hasReplacedHeater: ThreeChoicesAnswer hotWaterEquipment: HotWaterEquipment warmingFluid: WarmingType | null hotWaterFluid: FluidType | null cookingFluid: FluidType updateDate: DateTime } Each profileType value is an enum that you can find in the application. The values are set by default to a default profileType and needs to be completed by the user in order to become accurate. Profile type form User should answer a form to be able to set its profile type. Here is the flow of questions: Profile types handling over time A user can have many profileTypes, Ecolyo takes into account that one can move from his home, have more occupants, start renovating works and so on. That's why a profileType is only active for a given time period, this is how its time logic works. No filled profileType A default profileType is loaded in redux to operate basic operations. When the user looks at its analysis or options, ecolyo suggest user to fill a more accurate profileType. First profileType The profileType will follow the form logic above (see ProfileType form section). updateDate field will be the current month and year. Since this profileType will be the only one in database, getProfileType() method will always return it, therefore it will be used for all past time period on analysis. Following profileTypes Each new profileType form will show a calendar picking section at the end of the form. By default, current month and year will be selected. If current year is not yet completed (december not reached), month dropdown menu will only propose past and present months for this year. When finishing, before the new profileType is saved. Checks if other profileTypes exist on the period between selected month/year and present day. - If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some information before, this new profiletype will be more accurate). Then save profileType on given month/year. - If no other profileTypes are found, save profileType on given month/year. Profile type entity service Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getProfileType(date?: DateTime) : Promise-ProfileType, null Returns a profiletype closest to the given param date. When no param date, returns most recent profiletype getAllProfileTypes(timePeriod?: TimePeriod) : Promise-ProfileType[], null Returns all profiletypes for given time period, if no param returns all profiletypes updateProfileType(attributes: Partial-ProfileType): Promise-ProfileType, null Saves profiletype in couchdb deleteProfileTypes(profileTypes: ProfileType[]): Promise-boolean Delete array of profileTypes parseProfileTypeEntityToProfileType(profileTypeEntity: ProfileType): ProfileType Retrieves ProfileType from the ProfileTypeEntity Profile type service Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getMonthlyForecast(month: number) : Promise-MonthlyForecast Used to get the monthly forecast for a given month getFluidForecast(fluidType: FluidType, month: number) : Promise-FluidForecast Used to get the monthly forecast for a given FluidType getDetailsMonthlyForecast(fluidType: FluidType, month: number): Promise-DetailsMonthlyForecast Used to get the details of a fluidForecast. For each fluid return the related consumptions getMonthColdWaterConsumption(month: number): number Returns the cold water consumption in L for a given month getMonthElectricSpecificConsumption(month: number): number Returns the electric specific consumption in kWh for a given month getMonthCookingConsumption(month: number): number Returns the cooking consumption in kWh for a given month getMonthEcs(month: number) : number Returns the hot water consumption in kWh for a given month getMonthHeating(month: number): Promise-number Returns the heating consumption in kWh for a given month calculateTotalConsumption(spreadConsumption: number, profileType: ProfileType, month: number) : number Returns the total ECS consumption with applyied corrections to the spreadConsumption depending on users facilities. calculateSpreadNeeds(profileType: ProfileType, month: number): number Calculate the water spread consumption calculateMonthWaterRawNeeds(profileType: ProfileType, month: number) : number Returns the raw water needs of a home calculateWarmingEstimatedConsumption(): number Calculates the estimated consumption of a home calculateWarmingCorrectedConsumption(estimatedConsumption: number): number Apply the different corrections to the estimated heating consumption calculateWarmingMonthConsumption(correctedConsumption: number, month: number): Promise-number Apply dju ratio to the corrected heating consumption fetchDJU(month: number): Promise-number Returns a Promise with the dju for the given month Here is an example of a MonthlyForecast, which is the only function directly called by the analyzis component : { fluidForecast: [ { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: 266, heatingConsumption: 4074, }, fluidType: 0, load: 4340, value: 670.96, }, { detailsMonthlyForecast: { coldWaterConsumption: 14911, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 1, load: 14911, value: 46.224, }, { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: 85, ecsConsumption: 290, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 2, load: 375, value: 29.737, }, ], month: 1, totalValue: 746.921, } In these data, the load is in kWh for gaz and electricity (fluidtype 0 and 2) and in L for water. Value and totalValue are given in euros. The different consumption are distributed to their corresponding fluidType according to the variables warmingFluid, hotWaterFluid, cookingFluid . For example, if the cookingFluid is gaz, then its value will be stored in the fluidType 2 and nulled in the others. Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personal consumption, so it doesn't takes place in the calculation. DJU The method fetchDJU(month:number) tries to fetch the daily dju from the datagrandlyon API trough a remote doctype named org.ecolyo.dju . The data returned by this API are gathered by the lyon-bron-sta The API returns dju by day for a given month, so we add them to return a monthly dju. If remote doctype fails or return a null value, we returns instead the default dju stored in heating.json Useful tips while working with this API : Do not pass a Content-Type while requesting, it will returns error While requesting from a cozy instance, if you get errors, you will get errors from the cozy stack and not directly from the API, which leads to weird cases : If there is an authentication error, the api will returns an error in html format to cozy, so you'll get from cozy an error 502 as following, beacause cozy expects a json response : { \"status\" : \"502\" , \"title\" : \"Bad Gateway\" , \"detail\" : \"the content-type for the response is not authorized\" , \"source\" : {} } In case of bad request (wrong paramaters for example), the API will return an error in xml format so you'll get exaclty the same error as above in your cozy instance.","title":"Profile Type"},{"location":"ecolyo/functionalities/profile_type/#profile-type-data","text":"The profileType data are stored in the profile doctype and includes the following information : { housingType: HousingType constructionYear: ConstructionYear area: string occupantsNumber: number outsideFacingWalls: OutsideFacingWalls floor: Floor heating: IndividualOrCollective coldWater: IndividualOrCollective hotWater: IndividualOrCollective individualInsulationWork: IndividualInsulationWork[] hasInstalledVentilation: ThreeChoicesAnswer hasReplacedHeater: ThreeChoicesAnswer hotWaterEquipment: HotWaterEquipment warmingFluid: WarmingType | null hotWaterFluid: FluidType | null cookingFluid: FluidType updateDate: DateTime } Each profileType value is an enum that you can find in the application. The values are set by default to a default profileType and needs to be completed by the user in order to become accurate.","title":"Profile type data"},{"location":"ecolyo/functionalities/profile_type/#profile-type-form","text":"User should answer a form to be able to set its profile type. Here is the flow of questions:","title":"Profile type form"},{"location":"ecolyo/functionalities/profile_type/#profile-types-handling-over-time","text":"A user can have many profileTypes, Ecolyo takes into account that one can move from his home, have more occupants, start renovating works and so on. That's why a profileType is only active for a given time period, this is how its time logic works.","title":"Profile types handling over time"},{"location":"ecolyo/functionalities/profile_type/#no-filled-profiletype","text":"A default profileType is loaded in redux to operate basic operations. When the user looks at its analysis or options, ecolyo suggest user to fill a more accurate profileType.","title":"No filled profileType"},{"location":"ecolyo/functionalities/profile_type/#first-profiletype","text":"The profileType will follow the form logic above (see ProfileType form section). updateDate field will be the current month and year. Since this profileType will be the only one in database, getProfileType() method will always return it, therefore it will be used for all past time period on analysis.","title":"First profileType"},{"location":"ecolyo/functionalities/profile_type/#following-profiletypes","text":"Each new profileType form will show a calendar picking section at the end of the form. By default, current month and year will be selected. If current year is not yet completed (december not reached), month dropdown menu will only propose past and present months for this year. When finishing, before the new profileType is saved. Checks if other profileTypes exist on the period between selected month/year and present day. - If profileTypes are found, they are deleted (newest profileType always prevails on older ones, so that user had forgotten to fill some information before, this new profiletype will be more accurate). Then save profileType on given month/year. - If no other profileTypes are found, save profileType on given month/year.","title":"Following profileTypes"},{"location":"ecolyo/functionalities/profile_type/#profile-type-entity-service","text":"Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getProfileType(date?: DateTime) : Promise-ProfileType, null Returns a profiletype closest to the given param date. When no param date, returns most recent profiletype getAllProfileTypes(timePeriod?: TimePeriod) : Promise-ProfileType[], null Returns all profiletypes for given time period, if no param returns all profiletypes updateProfileType(attributes: Partial-ProfileType): Promise-ProfileType, null Saves profiletype in couchdb deleteProfileTypes(profileTypes: ProfileType[]): Promise-boolean Delete array of profileTypes parseProfileTypeEntityToProfileType(profileTypeEntity: ProfileType): ProfileType Retrieves ProfileType from the ProfileTypeEntity","title":"Profile type entity service"},{"location":"ecolyo/functionalities/profile_type/#profile-type-service","text":"Here you can see the different methods provided by the profileType service. These methods allows to calculate the average consumption depending on the information gathered in user's profileType. Method Description getMonthlyForecast(month: number) : Promise-MonthlyForecast Used to get the monthly forecast for a given month getFluidForecast(fluidType: FluidType, month: number) : Promise-FluidForecast Used to get the monthly forecast for a given FluidType getDetailsMonthlyForecast(fluidType: FluidType, month: number): Promise-DetailsMonthlyForecast Used to get the details of a fluidForecast. For each fluid return the related consumptions getMonthColdWaterConsumption(month: number): number Returns the cold water consumption in L for a given month getMonthElectricSpecificConsumption(month: number): number Returns the electric specific consumption in kWh for a given month getMonthCookingConsumption(month: number): number Returns the cooking consumption in kWh for a given month getMonthEcs(month: number) : number Returns the hot water consumption in kWh for a given month getMonthHeating(month: number): Promise-number Returns the heating consumption in kWh for a given month calculateTotalConsumption(spreadConsumption: number, profileType: ProfileType, month: number) : number Returns the total ECS consumption with applyied corrections to the spreadConsumption depending on users facilities. calculateSpreadNeeds(profileType: ProfileType, month: number): number Calculate the water spread consumption calculateMonthWaterRawNeeds(profileType: ProfileType, month: number) : number Returns the raw water needs of a home calculateWarmingEstimatedConsumption(): number Calculates the estimated consumption of a home calculateWarmingCorrectedConsumption(estimatedConsumption: number): number Apply the different corrections to the estimated heating consumption calculateWarmingMonthConsumption(correctedConsumption: number, month: number): Promise-number Apply dju ratio to the corrected heating consumption fetchDJU(month: number): Promise-number Returns a Promise with the dju for the given month Here is an example of a MonthlyForecast, which is the only function directly called by the analyzis component : { fluidForecast: [ { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: 266, heatingConsumption: 4074, }, fluidType: 0, load: 4340, value: 670.96, }, { detailsMonthlyForecast: { coldWaterConsumption: 14911, cookingConsumption: null, ecsConsumption: null, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 1, load: 14911, value: 46.224, }, { detailsMonthlyForecast: { coldWaterConsumption: null, cookingConsumption: 85, ecsConsumption: 290, electricSpecificConsumption: null, heatingConsumption: null, }, fluidType: 2, load: 375, value: 29.737, }, ], month: 1, totalValue: 746.921, } In these data, the load is in kWh for gaz and electricity (fluidtype 0 and 2) and in L for water. Value and totalValue are given in euros. The different consumption are distributed to their corresponding fluidType according to the variables warmingFluid, hotWaterFluid, cookingFluid . For example, if the cookingFluid is gaz, then its value will be stored in the fluidType 2 and nulled in the others. Also, we consider that if the heating or the hotwater are collective, we don't calcute it because the user can never access his personal consumption, so it doesn't takes place in the calculation.","title":"Profile type service"},{"location":"ecolyo/functionalities/profile_type/#dju","text":"The method fetchDJU(month:number) tries to fetch the daily dju from the datagrandlyon API trough a remote doctype named org.ecolyo.dju . The data returned by this API are gathered by the lyon-bron-sta The API returns dju by day for a given month, so we add them to return a monthly dju. If remote doctype fails or return a null value, we returns instead the default dju stored in heating.json Useful tips while working with this API : Do not pass a Content-Type while requesting, it will returns error While requesting from a cozy instance, if you get errors, you will get errors from the cozy stack and not directly from the API, which leads to weird cases : If there is an authentication error, the api will returns an error in html format to cozy, so you'll get from cozy an error 502 as following, beacause cozy expects a json response : { \"status\" : \"502\" , \"title\" : \"Bad Gateway\" , \"detail\" : \"the content-type for the response is not authorized\" , \"source\" : {} } In case of bad request (wrong paramaters for example), the API will return an error in xml format so you'll get exaclty the same error as above in your cozy instance.","title":"DJU"},{"location":"ecolyo/functionalities/terms/","text":"This section explains the way we handle terms in the application. Description The terms version is handled with the io.cozy.terms doctype. It is incremented each time we edit the CGU, the data consent validation or the legal notices. Once we increment the terms version, the user will be prompted to accept these terms, otherwise we won't be able to access the app. Private Routes All routes are private, and are accessible only if the user has accepted the last version of the terms. The only public routes are : /terms : shows the terms validation page, and is the main page the user is redirected to if his consent is outdated /cgu : shows the CGU public page, accessible by the terms page /legal : shows the Legal Notice public page, accessible by the terms page Terms managment We check the terms acceptation in the splash screen while the application is initializing, if there is no consent (first connection), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page. For the full terms acceptation process, the user has to check the two checkboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value accepted to true. So he can access now the entire application. We store in user's profile a boolean showConsentModal that allows the app to know about the consent status. If there is a consent update, two cases are possible : - It's a major update, ex: from 1.X.X to 2.X.X, the user has to go through the entire term validation process as explained above - It's a minor update, ex: from 1.1.X to 1.3.X or from 1.2.1 to 1.2.3, the user is just prompted with a modal with some text about the update, and a link to the legal notice, but there is no blocking acceptation input for the user. Version number The version number of the last terms is stored in the config.json file. If this version number doesn't correspond with the last term accepted, according the update version type (minor or major), the user won't be able to access the app and will be prompted to accept new terms or will simply be prompted. Global state Once the verification done in the splash screen , the last term state is stored in the redux store under the ecolyo.global state. The model is the following : termsStatus: { accepted: boolean, versionType: 'major' | 'minor' | 'init', }, Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connection or to case the last accepted term version is up to date.","title":"Terms"},{"location":"ecolyo/functionalities/terms/#description","text":"The terms version is handled with the io.cozy.terms doctype. It is incremented each time we edit the CGU, the data consent validation or the legal notices. Once we increment the terms version, the user will be prompted to accept these terms, otherwise we won't be able to access the app.","title":"Description"},{"location":"ecolyo/functionalities/terms/#private-routes","text":"All routes are private, and are accessible only if the user has accepted the last version of the terms. The only public routes are : /terms : shows the terms validation page, and is the main page the user is redirected to if his consent is outdated /cgu : shows the CGU public page, accessible by the terms page /legal : shows the Legal Notice public page, accessible by the terms page","title":"Private Routes"},{"location":"ecolyo/functionalities/terms/#terms-managment","text":"We check the terms acceptation in the splash screen while the application is initializing, if there is no consent (first connection), or the consent is outdated (update of terms), the user will be redirected to the terms acceptation page. For the full terms acceptation process, the user has to check the two checkboxes (one for Data share consent, and one for CGU and Legal Notice) to unlock the terms acceptation button. Once he has accepted it, a new term doctype is created with the value accepted to true. So he can access now the entire application. We store in user's profile a boolean showConsentModal that allows the app to know about the consent status. If there is a consent update, two cases are possible : - It's a major update, ex: from 1.X.X to 2.X.X, the user has to go through the entire term validation process as explained above - It's a minor update, ex: from 1.1.X to 1.3.X or from 1.2.1 to 1.2.3, the user is just prompted with a modal with some text about the update, and a link to the legal notice, but there is no blocking acceptation input for the user.","title":"Terms managment"},{"location":"ecolyo/functionalities/terms/#version-number","text":"The version number of the last terms is stored in the config.json file. If this version number doesn't correspond with the last term accepted, according the update version type (minor or major), the user won't be able to access the app and will be prompted to accept new terms or will simply be prompted.","title":"Version number"},{"location":"ecolyo/functionalities/terms/#global-state","text":"Once the verification done in the splash screen , the last term state is stored in the redux store under the ecolyo.global state. The model is the following : termsStatus: { accepted: boolean, versionType: 'major' | 'minor' | 'init', }, Major and minor value are only used in the case of an update. Otherwise we store the value 'init' which corresponds either to a first connection or to case the last accepted term version is up to date.","title":"Global state"},{"location":"ecolyo/functionalities/usage_events_tracking/","text":"Usage events tracking This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType. Usage events collection During the use of the application we stored some events link to an user action. Here are the list of collected usage events: Category Type Target Result Context Description Connection ConnectionEvent \"desktop\" or \"mobile\" User connects to the application. Navigation NavigationEvent Page_name User navigates to a targeted page. Konnector KonnectorConnectEvent Konnector_slug \"success\" or \"error\" User connects a konnector. Konnector KonnectorRefreshEvent Konnector_slug \"success\" or \"error\" User refreshes a konnector. Challenge ChallengeLaunchEvent Challenge_id User launches a challenge. Challenge ChallengeEndEvent Challenge_id User ends a challenge. Duel DuelLaunchEvent Duel_id Challenge_id User launches a duel. Duel DuelEndEvent Duel_id Challenge_id User ends a duel. Quiz QuizEndEvent Quiz_id starsNumber Challenge_id User ends a quiz. Exploration ExplorationEndEvent Exploration_id Challenge_id User ends an exploration. Action ActionChangeEvent Action_id Challenge_id User change action's ecogesture. Action ActionEndEvent Action_id Challenge_id User ends a action. Profile ProfileSetEvent User fills in its profile. Consumption ConsumptionCompareEvent Fluid / TimeStep User compares its consumption. Consumption ConsumptionChangeTimeStepEvent TimeStep Fluid User changes timeStep of its consumption. Consumption ConsumptionInteracteEvent Fluid / TimeStep User selects a consumption on the chart. All events are stored with the aggregated flag to false to allow the identification of new events. Usage events aggregator service Functionnalities The service will retrieve all new events by filter on the aggregated flag to false and the event date before than today. For each aggregator type we will defined the right calculation to apply to create the appropriate indicator: calculation of the session time indicator based on ConnectionEvent calculation of the konnectors connected per day based on the fluidStatus calculates if a user launched a duel just after earned 15 stars calculation of the period between 2 different challenges based on the ChallengeLaunchEvent calculation of the period between the first connection and the first challenge based on ChallengeLaunchEvent and ConnectionEvent calculation of an indicator based on a single event calculation of an aggregated indicator to sum an event type per days. Once the indicators is calculated we will: post the indicator to the remote doctype push the event used to calculate the indicator to a array, which will be used to identify all events taken into account during the process. At the end of the service, the service will change the aggregated flag to true for all events present in the array. More technical information are available here Remote doctype All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. Here are the actual structure of this remote doctype: { source: string name: string startDate: string endDate: string value?: number groups: { [key: string]: string } } with: source: contains \"ecolyo\" value. name: contains the indicator type startDate and endDate: used to defined a period or if not relevant, it contains both the date of the events. value: contains aggreated value (example: number of page viewed on a day). groups: contains all other attribute useful for the indicator (example: context, target, result)","title":"Usage events tracking"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-tracking","text":"This section explains how the application is tracking usage events. Here are the main step: All events are stored during the use of the application in the doctype com.grandlyon.ecolyo.usageevents A service is responsible of the aggregation of these events to create ANONYMIZED indicators. These indicators are then sent to a remote docType.","title":"Usage events tracking"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-collection","text":"During the use of the application we stored some events link to an user action. Here are the list of collected usage events: Category Type Target Result Context Description Connection ConnectionEvent \"desktop\" or \"mobile\" User connects to the application. Navigation NavigationEvent Page_name User navigates to a targeted page. Konnector KonnectorConnectEvent Konnector_slug \"success\" or \"error\" User connects a konnector. Konnector KonnectorRefreshEvent Konnector_slug \"success\" or \"error\" User refreshes a konnector. Challenge ChallengeLaunchEvent Challenge_id User launches a challenge. Challenge ChallengeEndEvent Challenge_id User ends a challenge. Duel DuelLaunchEvent Duel_id Challenge_id User launches a duel. Duel DuelEndEvent Duel_id Challenge_id User ends a duel. Quiz QuizEndEvent Quiz_id starsNumber Challenge_id User ends a quiz. Exploration ExplorationEndEvent Exploration_id Challenge_id User ends an exploration. Action ActionChangeEvent Action_id Challenge_id User change action's ecogesture. Action ActionEndEvent Action_id Challenge_id User ends a action. Profile ProfileSetEvent User fills in its profile. Consumption ConsumptionCompareEvent Fluid / TimeStep User compares its consumption. Consumption ConsumptionChangeTimeStepEvent TimeStep Fluid User changes timeStep of its consumption. Consumption ConsumptionInteracteEvent Fluid / TimeStep User selects a consumption on the chart. All events are stored with the aggregated flag to false to allow the identification of new events.","title":"Usage events collection"},{"location":"ecolyo/functionalities/usage_events_tracking/#usage-events-aggregator-service","text":"","title":"Usage events aggregator service"},{"location":"ecolyo/functionalities/usage_events_tracking/#functionnalities","text":"The service will retrieve all new events by filter on the aggregated flag to false and the event date before than today. For each aggregator type we will defined the right calculation to apply to create the appropriate indicator: calculation of the session time indicator based on ConnectionEvent calculation of the konnectors connected per day based on the fluidStatus calculates if a user launched a duel just after earned 15 stars calculation of the period between 2 different challenges based on the ChallengeLaunchEvent calculation of the period between the first connection and the first challenge based on ChallengeLaunchEvent and ConnectionEvent calculation of an indicator based on a single event calculation of an aggregated indicator to sum an event type per days. Once the indicators is calculated we will: post the indicator to the remote doctype push the event used to calculate the indicator to a array, which will be used to identify all events taken into account during the process. At the end of the service, the service will change the aggregated flag to true for all events present in the array. More technical information are available here","title":"Functionnalities"},{"location":"ecolyo/functionalities/usage_events_tracking/#remote-doctype","text":"All indicator are post to a remote doctype, which will allow the application to read a defined external API. This doctype is created by Cozy itself. Here are the actual structure of this remote doctype: { source: string name: string startDate: string endDate: string value?: number groups: { [key: string]: string } } with: source: contains \"ecolyo\" value. name: contains the indicator type startDate and endDate: used to defined a period or if not relevant, it contains both the date of the events. value: contains aggreated value (example: number of page viewed on a day). groups: contains all other attribute useful for the indicator (example: context, target, result)","title":"Remote doctype"},{"location":"ecolyo/getting_started/launch_local_application/","text":"This section will allow you to launch a proper local environment of the Ecolyo application Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo.git Installation of the project Installation of node modules To install required node module, open a terminal on the root folder of the project and type the following command: yarn install Start Ecolyo application To start ecolyo application just launch the command: yarn start If the application starts successfully you should obtain the following message: App successfully compiled! Dev assets:http://localhost:8888 Once the application is started, run the easy-cozy stack with docker. On windows and linux Launch the stack with the following command: docker-compose up A Powershell window will open. Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url: Cozy local url Local database can also be consulted at the following url: Cozy local DB Import mock data Requirement Your dev stack should be running to import the moke data First install ACH using yarn : yarn global add cozy-ach Next create the \"config.js\" file base on the \"config.template.js\" You can change the period of data generated by changing the following lines: const startingdate = DateTime.local() .plus({ days: -120 }) .startOf('day') const endingDate = DateTime.local() .plus({ days: -1 }) .startOf('day') Just replace -120 by the value needed Next launch the script createDayDataFiles.js available into the scripts folder cd scripts node createDayDataFiles.js Json files with data will be created into scripts/data folder. ACH script \"importData.bat\" will load the content of the file into your couchDB (database of your dev stack). Launch it using following commands: cd scripts ./importData.bat If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin . You'll be prompted for a cozysessid, you can get it in the web console ; in the application tab, look for the cookies and just copy the cozysessid value. A new browser windows will open and asking you approval to import data. Just click on Approve Finally your data is loaded in the Ecolyo Application ! Simulate konnectors connection Requirement Your dev stack should be running to import data needed to simulate konnectors connection When using local environment, konnectors are not able to connect. To simulate the connection you can use the script createConnection.js available in scripts folder. First update the authorization and cookie information from the \"config.js\" file (if not created just create it from the \"config.template.js\" file): const authorization = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' To obtain your own Bearer and cozysessid you need to have the application launched and display the web console (F12) in your navigator and select the Network tab. Just select one request and retrieve information for Request Header: Next launch the script : cd scripts node createConnections.js Your data is now loaded and you can refresh the application to see your konnector connected.","title":"Launch the application on local"},{"location":"ecolyo/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"ecolyo/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/web-et-numerique/llle_project/ecolyo.git","title":"Clone the project repository"},{"location":"ecolyo/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"ecolyo/getting_started/launch_local_application/#installation-of-node-modules","text":"To install required node module, open a terminal on the root folder of the project and type the following command: yarn install","title":"Installation of node modules"},{"location":"ecolyo/getting_started/launch_local_application/#start-ecolyo-application","text":"To start ecolyo application just launch the command: yarn start If the application starts successfully you should obtain the following message: App successfully compiled! Dev assets:http://localhost:8888 Once the application is started, run the easy-cozy stack with docker.","title":"Start Ecolyo application"},{"location":"ecolyo/getting_started/launch_local_application/#on-windows-and-linux","text":"Launch the stack with the following command: docker-compose up A Powershell window will open. Wait until the success message: Everything is setup. Go to http://ecolyo.cozy.tools:8080/ To exit, press ^C Once successfull you can launch your local cozy with following url: Cozy local url Local database can also be consulted at the following url: Cozy local DB","title":"On windows and linux"},{"location":"ecolyo/getting_started/launch_local_application/#import-mock-data","text":"Requirement Your dev stack should be running to import the moke data First install ACH using yarn : yarn global add cozy-ach Next create the \"config.js\" file base on the \"config.template.js\" You can change the period of data generated by changing the following lines: const startingdate = DateTime.local() .plus({ days: -120 }) .startOf('day') const endingDate = DateTime.local() .plus({ days: -1 }) .startOf('day') Just replace -120 by the value needed Next launch the script createDayDataFiles.js available into the scripts folder cd scripts node createDayDataFiles.js Json files with data will be created into scripts/data folder. ACH script \"importData.bat\" will load the content of the file into your couchDB (database of your dev stack). Launch it using following commands: cd scripts ./importData.bat If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin . You'll be prompted for a cozysessid, you can get it in the web console ; in the application tab, look for the cookies and just copy the cozysessid value. A new browser windows will open and asking you approval to import data. Just click on Approve Finally your data is loaded in the Ecolyo Application !","title":"Import mock data"},{"location":"ecolyo/getting_started/launch_local_application/#simulate-konnectors-connection","text":"Requirement Your dev stack should be running to import data needed to simulate konnectors connection When using local environment, konnectors are not able to connect. To simulate the connection you can use the script createConnection.js available in scripts folder. First update the authorization and cookie information from the \"config.js\" file (if not created just create it from the \"config.template.js\" file): const authorization = 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' To obtain your own Bearer and cozysessid you need to have the application launched and display the web console (F12) in your navigator and select the Network tab. Just select one request and retrieve information for Request Header: Next launch the script : cd scripts node createConnections.js Your data is now loaded and you can refresh the application to see your konnector connected.","title":"Simulate konnectors connection"},{"location":"ecolyo/getting_started/launch_local_konnector/","text":"Cozy ressources Please see also the official cozy documentation . Run a konnector locally To develop a konnector or test it, you will need to be able to run a konnector without the constraints imposed by the cozy stack. To help you, cozy developped a standalone mode for konnectors. Simply launch it by typing: yarn standalone This command will create a konnector-dev-config.json file if it was not in your project folder before. This file needs to hold all the information transmitted by the cozy stack when the konnector runs by default baseUrl apiAuthKey login password and so on... Type them all in the fields object. All data recovered by the standalone konnector will be stored in the data folder.","title":"Launch a konnector on local"},{"location":"ecolyo/getting_started/launch_local_konnector/#cozy-ressources","text":"Please see also the official cozy documentation .","title":"Cozy ressources"},{"location":"ecolyo/getting_started/launch_local_konnector/#run-a-konnector-locally","text":"To develop a konnector or test it, you will need to be able to run a konnector without the constraints imposed by the cozy stack. To help you, cozy developped a standalone mode for konnectors. Simply launch it by typing: yarn standalone This command will create a konnector-dev-config.json file if it was not in your project folder before. This file needs to hold all the information transmitted by the cozy stack when the konnector runs by default baseUrl apiAuthKey login password and so on... Type them all in the fields object. All data recovered by the standalone konnector will be stored in the data folder.","title":"Run a konnector locally"},{"location":"ecolyo/project_architecture/architecture/","text":"Architecture Principle diagram The principle diagram below describes the responsibilities of each application brick.","title":"Architecture"},{"location":"ecolyo/project_architecture/architecture/#architecture","text":"","title":"Architecture"},{"location":"ecolyo/project_architecture/architecture/#principle-diagram","text":"The principle diagram below describes the responsibilities of each application brick.","title":"Principle diagram"},{"location":"ecolyo/project_architecture/doctypes/","text":"Timeseries doctypes Description Each fluid has its own doctype wildcard and one doctype per time step. Each available time step for a fluid depends of the available data from the energy provider. Here are the different time step: half an hour - use com.grandlyon.*.minute doctype week - use com.grandlyon.*.day doctype day - use com.grandlyon.*.day doctype month - use com.grandlyon.*.month doctype year - use com.grandlyon.*.year doctype Doctype Here are the available doctypes: Fluid type Doctype wildcard Doctypes electricity fluid / enedis com.grandlyon.enedis.* com.grandlyon.enedis.minute com.grandlyon.enedis.day com.grandlyon.enedis.month com.grandlyon.enedis.year gaz fluid / grdf com.grandlyon.grdf.* com.grandlyon.grdf.day com.grandlyon.grdf.month com.grandlyon.grdf.year water fluid / eau du grand lyon com.grandlyon.egl.* com.grandlyon.egl.day com.grandlyon.egl.month com.grandlyon.egl.year Structure Field Type Description load number load (in kWh or L) minute number minute of the date set to 0 except for minute serie hour number hour of the date set to 0 except for minute and hour series day number day of the date set to 1 for month and year series month number month of the date set to 1 for year series year number year of the date Example { \"load\": 770.18, \"minute\": 0, \"hour\": 0, \"day\": 1, \"month\": 1, \"year\": 2020 } User profile Description This doctype is used to store all information about the user. Doctype com.grandlyon.ecolyo.profile Structure Field Type Description id string Profile id ecogestureHash string Hash used to verify the content of ecogestures challengeHash string Hash used to verify the content of challenges duelHash string Hash used to verify the content of duels quizHash string Hash used to verify the content of quiz explorationHash string Hash used to verify the content of exploration isFirstConnection boolean Boolean used to inform if the user connects for the first time lastConnectionDate DateTime Date of the last user connection haveSeenLastAnalysis boolean Boolean used to inform if user has seen the last analysis haveSeenOldFluidModal Datetime or boolean Used to inform if user has seen the modal display when his data are too old. Its value is false or a DateTime when he saw it sendAnalysisNotification boolean Boolean used to inform if user has seen the analysis notification monthlyAnalysisDate DateTime Date of the last monthly analysis profileType ProfileType User consumption profile isProfileTypeCompleted boolean Check if a user has completed his consumption profile showConsentModal boolean Boolean used to show the terms acceptation page, and to protect the app private routes if last terms are not accepted or outdated Example { \"id\": \"0e016e853592e18155e87b85ce00a33a\", \"challengeHash\": \"4cbcafe514788757c377534f1a407e022c29e38c\", \"duelHash\": \"48371ffabb2853b0503b882f11e1fa8e730bac76\", \"ecogestureHash\": \"9798a0aaccb47cff906fc4931a2eff5f9371dd8b\", \"haveSeenLastAnalysis\": true, \"haveSeenOldFluidModal\": false, \"isFirstConnection\": false, \"lastConnectionDate\": \"2021-03-08T17:33:18.727Z\", \"monthlyAnalysisDate\": \"2021-01-03T00:00:00.000+01:00\", \"quizHash\": \"11372a56c03edef1d6656f8a76d5ec457174f2c1\", \"explorationHash\": \"cdbc7a84d041318253a10b3cc0c02f9020c78c0b\", \"sendAnalysisNotification\": false, \"profileType\": { \"area\": \"123\", \"coldWater\": \"individual\", \"constructionYear\": \"between_1948_and_1974\", \"cookingFluid\": 0, \"floor\": \"not_applicable\", \"hasInstalledVentilation\": \"yes\", \"hasReplacedHeater\": \"yes\", \"heating\": \"individual\", \"hotWater\": \"individual\", \"hotWaterEquipment\": \"solar\", \"hotWaterFluid\": 0, \"housingType\": \"individual_house\", \"individualInsulationWork\": [ \"roof_insulation\" ], \"occupantsNumber\": 1, \"outsideFacingWalls\": \"2\", \"warmingFluid\": 0 }, \"isProfileTypeCompleted\": true, \"showConsentModal\": true } Ecogesture Description This doctype is used to store ecogestures. Doctype com.grandlyon.ecolyo.ecogesture Structure Field Type Description id string ecogesture id shortName string short name of the ecogesture longName string long name of the ecogesture longDescription string long description of the ecogesture usage Usage usage of the ecogesture Usage enum: - ALL = 0 - HEATING = 1 - AIR_CONDITIONING = 2 - ECS = 3 - COLD_WATER = 4 - ELECTRICITY_SPECIFIC = 5 - COOKING = 6 fluidTypes FluidType[] Array of fluid type on which ecogesture can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 impactLevel number impact level of the ecogesture efficiency number efficiency of the ecogesture difficulty number difficulty of the ecogesture room Room room affected by the ecogesture Room enum: - ALL = 0 - BATHROOM = 1 - KITCHEN = 2 - LAUNDRY = 3 - TOILET = 4 season Season season suited to the ecogesture Season enum: - NONE = 'Sans saison' - WINTER = 'Hiver' - SUMMER = 'Et\u00e9' equipment boolean used to know if one or more equipment are affected by the ecogesture equipmentType EquipmentType[] equipment affected by the ecogesture EquipmentType enum: - AIR_CONDITIONING = 0 - COMPUTER = 1 - MICROWAVE = 2 - OVEN = 3 - WASHING_MACHINE = 4 - DISHWASHER = 5 - COOKING_PLATES = 6 - DRYER = 7 - REFREGIRATOR = 8 - GARDEN = 9 - WATER_HEATER = 10 - FAN = 11 - CURTAIN = 12 - INTERNET_BOX = 13 - VENTILATION = 14 - FREEZER = 15 - BOILER = 16 - HYDRAULIC_HEATING = 17 equipmentInstallation boolean used to know if it is required an installation investment string or null investment required action boolean used to know if the ecogesture is used for action challenge actionName string or null action description of the ecogesture actionDuration number duration required to do an action challenge Example { \"shortName\": \"D\u00e9esse des eaux\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"usage\": 3, \"fluidTypes\": [ 1 ], \"impactLevel\": 5, \"investment\": null, \"room\": [ 1 ], \"difficulty\": 1, \"efficiency\": 4, \"season\": \"Sans saison\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], } Challenge Description This doctype is used to store all challenges. Doctype com.grandlyon.ecolyo.challenge Structure Field Type Description _id string challenge id - respect the format CHALLENGE000X title string title of the challenge description string description of the challenge target number The number of stars required to unlock the duel relationships any relation to quiz and duel Example { \"_id\": \"CHALLENGE0001\", \"title\": \"Nicolas Hublot\", \"description\": \"foobar\", \"target\": 15, \"relationships\": { \"quiz\": { \"data\": { \"_id\": \"QUIZ001\", \"_type\": \"com.grandlyon.ecolyo.quiz\" } }, \"exploration\": { \"data\": { \"_id\": \"EXPLORATION001\", \"_type\": \"com.grandlyon.ecolyo.exploration\" } }, \"duel\": { \"data\": { \"_id\": \"DUEL001\", \"_type\": \"com.grandlyon.ecolyo.duel\" } } } } User challenge Description This doctype is used to store all additionnal information about a challenge started or ended by the user. Doctype com.grandlyon.ecolyo.userchallenge Structure Field Type Description id string userChallenge id title string userChallenge title state UserChallengeState state of the challenge UserChallengeState enum - LOCKED = 0 - UNLOCKED = 1 - ONGOING = 2 - DUEL = 3 - DONE = 4 target number Number of stars required to unlock the duel progress ChallengeProgress Number of stars earned by the user for each challenge ChallengeProgress enum - quizzProgress: number - explorationProgress: number - actionProgress: number quiz UserQuiz Complete Quiz object with progress exploration UserExploration Complete Exploration object with progress action UserActionEntity Complete Action object duel UserDuelEntity Complete Duel object with progress included success UserChallengeSuccess Success state of the challenge UserChallengeSuccess enum - ONGOING = 0 - LOST = 1 - WIN = 2 startDate string null starting date of the the challenge endingDate string null ending date of the challenge Example { \"_id\": \"eae3a79a05d677a739bdd2b46b009936\", \"description\": \"foobar\", \"duel\": { \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 }, \"fluidTypes\": [ 0, 1, 2 ], \"id\": \"DUEL001\", \"startDate\": null, \"state\": 4, \"threshold\": -1, \"title\": \"Nicolas Hublot\", \"userConsumption\": 0 }, \"endingDate\": null, \"id\": \"CHALLENGE0001\", \"progress\": { \"actionProgress\": 0, \"explorationProgress\": 0, \"quizProgress\": 0 }, \"quiz\": { \"customQuestion\": { \"interval\": 30, \"period\": {}, \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"result\": 1, \"timeStep\": 20, \"type\": 0 }, \"id\": \"QUIZ001\", \"questions\": [ { \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"result\": 1, \"source\": \"string\" } ], \"result\": 5, \"state\": 2 }, \"exploration\": { \"id\": \"EXPLORATION001\", \"date\": \"2021-01-13T17:03:11.964Z\", \"description\": \"Consultez 3 fois Ecolyo\", \"ecogesture_id\": \"\", \"fluid_condition\": [], \"message_success\": \"Vous vous \u00eates connect\u00e9 3 fois \u00e0 Ecolyo\", \"progress\": 0, \"state\": 2, \"target\": 3, \"type\": 2 }, \"action\": { \"ecogesture\": { \"_id\": \"ECOGESTURE0004\", \"_rev\": \"3-da2ad5c7b81e4260e2254c98ec6ee971\", \"_type\": \"com.grandlyon.ecolyo.ecogesture\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"cozyMetadata\": { \"createdAt\": \"2021-03-08T09:52:41.029Z\", \"createdByApp\": \"Ecolyo\", \"createdByAppVersion\": \"1.0.4\", \"metadataVersion\": 1, \"updatedAt\": \"2021-03-08T09:52:41.029Z\", \"updatedByApps\": [ { \"date\": \"2021-03-08T09:52:41.029Z\", \"slug\": \"Ecolyo\", \"version\": \"1.0.4\" } ] }, \"difficulty\": 1, \"efficiency\": 2.5, \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], \"fluidTypes\": [ 1 ], \"id\": \"ECOGESTURE0004\", \"impactLevel\": 5, \"investment\": null, \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"room\": [ 1 ], \"season\": \"Sans saison\", \"shortName\": \"D\u00e9esse des eaux\", \"usage\": 3 }, \"startDate\": \"2021-03-09T17:57:44.600Z\", \"state\": 1 }, \"startDate\": \"2021-01-04T00:00:00.000Z\", \"state\": 3, \"success\": 0, \"target\": 15, \"title\": \"Nicolas Hublot\" } Quiz Description This doctype is used to store all quiz. Doctype com.grandlyon.ecolyo.quiz Structure Field Type Description _id string quiz id - respect the format QUIZ00X questions QuestionEntity[] Array of questions entities customQuestion CustomQuestionEntity Custom question based on user's consumption Example { \"_id\": \"QUIZ001\", \"questions\": [ { \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"source\": \"string\" }, { \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"source\": \"string\" } ], \"customQuestion\": { \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"type\": 0, \"timeStep\": 20, \"interval\": 30, \"period\": {}, \"singleFluid\": true } } Exploration Description This doctype is used to store all explorations. Doctype com.grandlyon.ecolyo.exploration Structure Field Type Description _id string exploration id - respect the format EXPLORATION00X state UserExplorationState State of the exploration UserExplorationState enum - UNLOCKED = 0 - ONGOING = 1 - DONE = 2 description string description of the exploration target number number of stars required to unlock an exploration type UserExplorationType type of the exploration UserExplorationType enum - DECLARATIVE = 0 - ACTION = 1 - CONSUMPTION = 2 - ECOGESTURE = 3 date string or null date of the exploration ecogesture_id string ecogesture's id fluid_condition FluidType[] Array of fluid type on which an exploration can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 message_success string message when exploration is done Example { \"_id\": \"EXPLORATION001\", \"description\": \"Consultez l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"target\": 1, \"type\": 3, \"date\": null, \"ecogesture_id\": \"0032\", \"fluid_condition\": [], \"message_success\": \"Vous avez consult\u00e9 l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"state\": 0, } Duel Description This doctype is used to store all duels. Doctype com.grandlyon.ecolyo.duel Structure Field Type Description _id string duel id - respect the format DUEL00X title string title of the duel description string description of the duel duration Duration Luxon Duration of the duel Example { \"_id\": \"DUEL001\", \"title\": \"Nicolas Hublot\", \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 } } Usage event Description This doctype is used to store all usage events. Doctype com.grandlyon.ecolyo.usageevent Structure Field Type Description date DateTime Date of the event type UsageEventType Type of the event target string Targeted konnector, page, challenge, quiz, exploration, action or timeStep result string Result for KonnectorConnectEvent or KonnectorRefreshEvent. Values: \"success\" or \"error\" context string Luxon Duration of the duel Terms Description This doctype is used to store the different version of the terms of the application. Doctype io.cozy.terms Structure Field Type Description accepted boolean The fact that the terms has been accepted by the Cozy user or not acceptedAt DateTime The date when the Cozy user accepted these terms termsId string The id of the terms version string The version number MaxPower Description This doctype is used to store the enedis maxpower values retrieved by the konnector on a daily basis. The value is in kVA. Doctype com.grandlyon.enedis.maxpower Structure Field Type Description load number maxpower in kVA minute number minute of the date hour number hour of the date day number day of the date month number month of the date year number year of the date Enedis Monthly Analysis Data Description This doctype is used to store the enedis monthly analysis, it includes the month average half-hour consumption for weekdays and weekends, the minimum half-hour load, and the max power consumption of the month. Doctype com.grandlyon.enedis.monthly.analysis.data Structure Field Type Description weekDaysHalfHourAverageValues number[] Half-hour average value for week days (monday to friday) weekEndDaysHalfHourAverageValues number[] Half-hour average value for weekend days (saturday and sunday) month number Month of the analysis year number Year of the analysis minLoad number or null Minimum half hour load of the month maxpower number or null Max power value of the month","title":"Doctypes"},{"location":"ecolyo/project_architecture/doctypes/#timeseries-doctypes","text":"","title":"Timeseries doctypes"},{"location":"ecolyo/project_architecture/doctypes/#description","text":"Each fluid has its own doctype wildcard and one doctype per time step. Each available time step for a fluid depends of the available data from the energy provider. Here are the different time step: half an hour - use com.grandlyon.*.minute doctype week - use com.grandlyon.*.day doctype day - use com.grandlyon.*.day doctype month - use com.grandlyon.*.month doctype year - use com.grandlyon.*.year doctype","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype","text":"Here are the available doctypes: Fluid type Doctype wildcard Doctypes electricity fluid / enedis com.grandlyon.enedis.* com.grandlyon.enedis.minute com.grandlyon.enedis.day com.grandlyon.enedis.month com.grandlyon.enedis.year gaz fluid / grdf com.grandlyon.grdf.* com.grandlyon.grdf.day com.grandlyon.grdf.month com.grandlyon.grdf.year water fluid / eau du grand lyon com.grandlyon.egl.* com.grandlyon.egl.day com.grandlyon.egl.month com.grandlyon.egl.year","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure","text":"Field Type Description load number load (in kWh or L) minute number minute of the date set to 0 except for minute serie hour number hour of the date set to 0 except for minute and hour series day number day of the date set to 1 for month and year series month number month of the date set to 1 for year series year number year of the date","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example","text":"{ \"load\": 770.18, \"minute\": 0, \"hour\": 0, \"day\": 1, \"month\": 1, \"year\": 2020 }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#user-profile","text":"","title":"User profile"},{"location":"ecolyo/project_architecture/doctypes/#description_1","text":"This doctype is used to store all information about the user.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_1","text":"com.grandlyon.ecolyo.profile","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_1","text":"Field Type Description id string Profile id ecogestureHash string Hash used to verify the content of ecogestures challengeHash string Hash used to verify the content of challenges duelHash string Hash used to verify the content of duels quizHash string Hash used to verify the content of quiz explorationHash string Hash used to verify the content of exploration isFirstConnection boolean Boolean used to inform if the user connects for the first time lastConnectionDate DateTime Date of the last user connection haveSeenLastAnalysis boolean Boolean used to inform if user has seen the last analysis haveSeenOldFluidModal Datetime or boolean Used to inform if user has seen the modal display when his data are too old. Its value is false or a DateTime when he saw it sendAnalysisNotification boolean Boolean used to inform if user has seen the analysis notification monthlyAnalysisDate DateTime Date of the last monthly analysis profileType ProfileType User consumption profile isProfileTypeCompleted boolean Check if a user has completed his consumption profile showConsentModal boolean Boolean used to show the terms acceptation page, and to protect the app private routes if last terms are not accepted or outdated","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_1","text":"{ \"id\": \"0e016e853592e18155e87b85ce00a33a\", \"challengeHash\": \"4cbcafe514788757c377534f1a407e022c29e38c\", \"duelHash\": \"48371ffabb2853b0503b882f11e1fa8e730bac76\", \"ecogestureHash\": \"9798a0aaccb47cff906fc4931a2eff5f9371dd8b\", \"haveSeenLastAnalysis\": true, \"haveSeenOldFluidModal\": false, \"isFirstConnection\": false, \"lastConnectionDate\": \"2021-03-08T17:33:18.727Z\", \"monthlyAnalysisDate\": \"2021-01-03T00:00:00.000+01:00\", \"quizHash\": \"11372a56c03edef1d6656f8a76d5ec457174f2c1\", \"explorationHash\": \"cdbc7a84d041318253a10b3cc0c02f9020c78c0b\", \"sendAnalysisNotification\": false, \"profileType\": { \"area\": \"123\", \"coldWater\": \"individual\", \"constructionYear\": \"between_1948_and_1974\", \"cookingFluid\": 0, \"floor\": \"not_applicable\", \"hasInstalledVentilation\": \"yes\", \"hasReplacedHeater\": \"yes\", \"heating\": \"individual\", \"hotWater\": \"individual\", \"hotWaterEquipment\": \"solar\", \"hotWaterFluid\": 0, \"housingType\": \"individual_house\", \"individualInsulationWork\": [ \"roof_insulation\" ], \"occupantsNumber\": 1, \"outsideFacingWalls\": \"2\", \"warmingFluid\": 0 }, \"isProfileTypeCompleted\": true, \"showConsentModal\": true }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#ecogesture","text":"","title":"Ecogesture"},{"location":"ecolyo/project_architecture/doctypes/#description_2","text":"This doctype is used to store ecogestures.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_2","text":"com.grandlyon.ecolyo.ecogesture","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_2","text":"Field Type Description id string ecogesture id shortName string short name of the ecogesture longName string long name of the ecogesture longDescription string long description of the ecogesture usage Usage usage of the ecogesture Usage enum: - ALL = 0 - HEATING = 1 - AIR_CONDITIONING = 2 - ECS = 3 - COLD_WATER = 4 - ELECTRICITY_SPECIFIC = 5 - COOKING = 6 fluidTypes FluidType[] Array of fluid type on which ecogesture can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 impactLevel number impact level of the ecogesture efficiency number efficiency of the ecogesture difficulty number difficulty of the ecogesture room Room room affected by the ecogesture Room enum: - ALL = 0 - BATHROOM = 1 - KITCHEN = 2 - LAUNDRY = 3 - TOILET = 4 season Season season suited to the ecogesture Season enum: - NONE = 'Sans saison' - WINTER = 'Hiver' - SUMMER = 'Et\u00e9' equipment boolean used to know if one or more equipment are affected by the ecogesture equipmentType EquipmentType[] equipment affected by the ecogesture EquipmentType enum: - AIR_CONDITIONING = 0 - COMPUTER = 1 - MICROWAVE = 2 - OVEN = 3 - WASHING_MACHINE = 4 - DISHWASHER = 5 - COOKING_PLATES = 6 - DRYER = 7 - REFREGIRATOR = 8 - GARDEN = 9 - WATER_HEATER = 10 - FAN = 11 - CURTAIN = 12 - INTERNET_BOX = 13 - VENTILATION = 14 - FREEZER = 15 - BOILER = 16 - HYDRAULIC_HEATING = 17 equipmentInstallation boolean used to know if it is required an installation investment string or null investment required action boolean used to know if the ecogesture is used for action challenge actionName string or null action description of the ecogesture actionDuration number duration required to do an action challenge","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_2","text":"{ \"shortName\": \"D\u00e9esse des eaux\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"usage\": 3, \"fluidTypes\": [ 1 ], \"impactLevel\": 5, \"investment\": null, \"room\": [ 1 ], \"difficulty\": 1, \"efficiency\": 4, \"season\": \"Sans saison\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#challenge","text":"","title":"Challenge"},{"location":"ecolyo/project_architecture/doctypes/#description_3","text":"This doctype is used to store all challenges.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_3","text":"com.grandlyon.ecolyo.challenge","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_3","text":"Field Type Description _id string challenge id - respect the format CHALLENGE000X title string title of the challenge description string description of the challenge target number The number of stars required to unlock the duel relationships any relation to quiz and duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_3","text":"{ \"_id\": \"CHALLENGE0001\", \"title\": \"Nicolas Hublot\", \"description\": \"foobar\", \"target\": 15, \"relationships\": { \"quiz\": { \"data\": { \"_id\": \"QUIZ001\", \"_type\": \"com.grandlyon.ecolyo.quiz\" } }, \"exploration\": { \"data\": { \"_id\": \"EXPLORATION001\", \"_type\": \"com.grandlyon.ecolyo.exploration\" } }, \"duel\": { \"data\": { \"_id\": \"DUEL001\", \"_type\": \"com.grandlyon.ecolyo.duel\" } } } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#user-challenge","text":"","title":"User challenge"},{"location":"ecolyo/project_architecture/doctypes/#description_4","text":"This doctype is used to store all additionnal information about a challenge started or ended by the user.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_4","text":"com.grandlyon.ecolyo.userchallenge","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_4","text":"Field Type Description id string userChallenge id title string userChallenge title state UserChallengeState state of the challenge UserChallengeState enum - LOCKED = 0 - UNLOCKED = 1 - ONGOING = 2 - DUEL = 3 - DONE = 4 target number Number of stars required to unlock the duel progress ChallengeProgress Number of stars earned by the user for each challenge ChallengeProgress enum - quizzProgress: number - explorationProgress: number - actionProgress: number quiz UserQuiz Complete Quiz object with progress exploration UserExploration Complete Exploration object with progress action UserActionEntity Complete Action object duel UserDuelEntity Complete Duel object with progress included success UserChallengeSuccess Success state of the challenge UserChallengeSuccess enum - ONGOING = 0 - LOST = 1 - WIN = 2 startDate string null starting date of the the challenge endingDate string null ending date of the challenge","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_4","text":"{ \"_id\": \"eae3a79a05d677a739bdd2b46b009936\", \"description\": \"foobar\", \"duel\": { \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 }, \"fluidTypes\": [ 0, 1, 2 ], \"id\": \"DUEL001\", \"startDate\": null, \"state\": 4, \"threshold\": -1, \"title\": \"Nicolas Hublot\", \"userConsumption\": 0 }, \"endingDate\": null, \"id\": \"CHALLENGE0001\", \"progress\": { \"actionProgress\": 0, \"explorationProgress\": 0, \"quizProgress\": 0 }, \"quiz\": { \"customQuestion\": { \"interval\": 30, \"period\": {}, \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"result\": 1, \"timeStep\": 20, \"type\": 0 }, \"id\": \"QUIZ001\", \"questions\": [ { \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"result\": 1, \"source\": \"string\" }, { \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"result\": 1, \"source\": \"string\" } ], \"result\": 5, \"state\": 2 }, \"exploration\": { \"id\": \"EXPLORATION001\", \"date\": \"2021-01-13T17:03:11.964Z\", \"description\": \"Consultez 3 fois Ecolyo\", \"ecogesture_id\": \"\", \"fluid_condition\": [], \"message_success\": \"Vous vous \u00eates connect\u00e9 3 fois \u00e0 Ecolyo\", \"progress\": 0, \"state\": 2, \"target\": 3, \"type\": 2 }, \"action\": { \"ecogesture\": { \"_id\": \"ECOGESTURE0004\", \"_rev\": \"3-da2ad5c7b81e4260e2254c98ec6ee971\", \"_type\": \"com.grandlyon.ecolyo.ecogesture\", \"action\": true, \"actionDuration\": 3, \"actionName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"cozyMetadata\": { \"createdAt\": \"2021-03-08T09:52:41.029Z\", \"createdByApp\": \"Ecolyo\", \"createdByAppVersion\": \"1.0.4\", \"metadataVersion\": 1, \"updatedAt\": \"2021-03-08T09:52:41.029Z\", \"updatedByApps\": [ { \"date\": \"2021-03-08T09:52:41.029Z\", \"slug\": \"Ecolyo\", \"version\": \"1.0.4\" } ] }, \"difficulty\": 1, \"efficiency\": 2.5, \"equipment\": false, \"equipmentInstallation\": true, \"equipmentType\": [], \"fluidTypes\": [ 1 ], \"id\": \"ECOGESTURE0004\", \"impactLevel\": 5, \"investment\": null, \"longDescription\": \"Si vous n\u2019\u00eates pas frileux, coupez l'eau pendant que vous vous savonnez : l'\u00e9conomie en eau peut aller jusqu'\u00e0 50% !\", \"longName\": \"Je coupe l'eau de la douche pendant que je me savonne.\", \"room\": [ 1 ], \"season\": \"Sans saison\", \"shortName\": \"D\u00e9esse des eaux\", \"usage\": 3 }, \"startDate\": \"2021-03-09T17:57:44.600Z\", \"state\": 1 }, \"startDate\": \"2021-01-04T00:00:00.000Z\", \"state\": 3, \"success\": 0, \"target\": 15, \"title\": \"Nicolas Hublot\" }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#quiz","text":"","title":"Quiz"},{"location":"ecolyo/project_architecture/doctypes/#description_5","text":"This doctype is used to store all quiz.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_5","text":"com.grandlyon.ecolyo.quiz","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_5","text":"Field Type Description _id string quiz id - respect the format QUIZ00X questions QuestionEntity[] Array of questions entities customQuestion CustomQuestionEntity Custom question based on user's consumption","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_5","text":"{ \"_id\": \"QUIZ001\", \"questions\": [ { \"questionLabel\": \"Quelle longueur faisait l\u2019aqueduc du Gier pour acheminer l\u2019eau sur Lyon \u00e0 l\u2019\u00e9poque romaine ?\", \"answers\": [ { \"answerLabel\": \"86 km\", \"isTrue\": true }, { \"answerLabel\": \"78 km\", \"isTrue\": false }, { \"answerLabel\": \"56 km\", \"isTrue\": false } ], \"explanation\": \"L\u2019aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant aliment\u00e9 la ville en eau, et celui dont les structures sont le mieux conserv\u00e9es. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rh\u00f4ne\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle type de pompes \u00e9taient utilis\u00e9es \u00e0 l'usine des eaux de Caluire jusqu'en 1910 ?\", \"answers\": [ { \"answerLabel\": \"Pompe \u00e0 cordes\", \"isTrue\": true }, { \"answerLabel\": \"Pompe de Cornouailles\", \"isTrue\": false }, { \"answerLabel\": \"Pompe \u00e0 air\", \"isTrue\": false } ], \"explanation\": \"Mise en fonctionnement en 1856, 3 pompes \u00e0 vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.\", \"source\": \"string\" }, { \"questionLabel\": \"Quelle est le nom du principal champ de captage d\u2019eau potable de la M\u00e9tropole ?\", \"answers\": [ { \"answerLabel\": \"Cr\u00e9mieux\", \"isTrue\": false }, { \"answerLabel\": \"Cr\u00e9pieux-Charmy\", \"isTrue\": true }, { \"answerLabel\": \"Charly\", \"isTrue\": false } ], \"explanation\": \"Cr\u00e9pieux-Charmy est le principal champ captant de la M\u00e9tropole de Lyon\", \"source\": \"string\" }, { \"questionLabel\": \"De quoi les nuages sont-ils constitu\u00e9s ?\", \"answers\": [ { \"answerLabel\": \"Vapeur d'eau\", \"isTrue\": false }, { \"answerLabel\": \"Fum\u00e9e\", \"isTrue\": false }, { \"answerLabel\": \"Gouttelettes d'eau et cristaux de glace\", \"isTrue\": true } ], \"explanation\": \"Les nuages sont constitu\u00e9s de gouttelettes d'eau et parfois aussi de cristaux de glace\", \"source\": \"string\" } ], \"customQuestion\": { \"questionLabel\": \"Quel jour ai-je le plus consomm\u00e9 la semaine derni\u00e8re ?\", \"type\": 0, \"timeStep\": 20, \"interval\": 30, \"period\": {}, \"singleFluid\": true } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#exploration","text":"","title":"Exploration"},{"location":"ecolyo/project_architecture/doctypes/#description_6","text":"This doctype is used to store all explorations.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_6","text":"com.grandlyon.ecolyo.exploration","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_6","text":"Field Type Description _id string exploration id - respect the format EXPLORATION00X state UserExplorationState State of the exploration UserExplorationState enum - UNLOCKED = 0 - ONGOING = 1 - DONE = 2 description string description of the exploration target number number of stars required to unlock an exploration type UserExplorationType type of the exploration UserExplorationType enum - DECLARATIVE = 0 - ACTION = 1 - CONSUMPTION = 2 - ECOGESTURE = 3 date string or null date of the exploration ecogesture_id string ecogesture's id fluid_condition FluidType[] Array of fluid type on which an exploration can have an impact FluidType enum: - ELECTRICITY = 0 - WATER = 1 - GAS = 2 - MULTIFLUID = 3 message_success string message when exploration is done","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_6","text":"{ \"_id\": \"EXPLORATION001\", \"description\": \"Consultez l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"target\": 1, \"type\": 3, \"date\": null, \"ecogesture_id\": \"0032\", \"fluid_condition\": [], \"message_success\": \"Vous avez consult\u00e9 l'\u00e9cogeste Chat \u00e9chaud\u00e9\", \"state\": 0, }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#duel","text":"","title":"Duel"},{"location":"ecolyo/project_architecture/doctypes/#description_7","text":"This doctype is used to store all duels.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_7","text":"com.grandlyon.ecolyo.duel","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_7","text":"Field Type Description _id string duel id - respect the format DUEL00X title string title of the duel description string description of the duel duration Duration Luxon Duration of the duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#example_7","text":"{ \"_id\": \"DUEL001\", \"title\": \"Nicolas Hublot\", \"description\": \"Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION \u20ac en 1 semaine\", \"duration\": { \"days\": 7 } }","title":"Example"},{"location":"ecolyo/project_architecture/doctypes/#usage-event","text":"","title":"Usage event"},{"location":"ecolyo/project_architecture/doctypes/#description_8","text":"This doctype is used to store all usage events.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_8","text":"com.grandlyon.ecolyo.usageevent","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_8","text":"Field Type Description date DateTime Date of the event type UsageEventType Type of the event target string Targeted konnector, page, challenge, quiz, exploration, action or timeStep result string Result for KonnectorConnectEvent or KonnectorRefreshEvent. Values: \"success\" or \"error\" context string Luxon Duration of the duel","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#terms","text":"","title":"Terms"},{"location":"ecolyo/project_architecture/doctypes/#description_9","text":"This doctype is used to store the different version of the terms of the application.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_9","text":"io.cozy.terms","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_9","text":"Field Type Description accepted boolean The fact that the terms has been accepted by the Cozy user or not acceptedAt DateTime The date when the Cozy user accepted these terms termsId string The id of the terms version string The version number","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#maxpower","text":"","title":"MaxPower"},{"location":"ecolyo/project_architecture/doctypes/#description_10","text":"This doctype is used to store the enedis maxpower values retrieved by the konnector on a daily basis. The value is in kVA.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_10","text":"com.grandlyon.enedis.maxpower","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_10","text":"Field Type Description load number maxpower in kVA minute number minute of the date hour number hour of the date day number day of the date month number month of the date year number year of the date","title":"Structure"},{"location":"ecolyo/project_architecture/doctypes/#enedis-monthly-analysis-data","text":"","title":"Enedis Monthly Analysis Data"},{"location":"ecolyo/project_architecture/doctypes/#description_11","text":"This doctype is used to store the enedis monthly analysis, it includes the month average half-hour consumption for weekdays and weekends, the minimum half-hour load, and the max power consumption of the month.","title":"Description"},{"location":"ecolyo/project_architecture/doctypes/#doctype_11","text":"com.grandlyon.enedis.monthly.analysis.data","title":"Doctype"},{"location":"ecolyo/project_architecture/doctypes/#structure_11","text":"Field Type Description weekDaysHalfHourAverageValues number[] Half-hour average value for week days (monday to friday) weekEndDaysHalfHourAverageValues number[] Half-hour average value for weekend days (saturday and sunday) month number Month of the analysis year number Year of the analysis minLoad number or null Minimum half hour load of the month maxpower number or null Max power value of the month","title":"Structure"},{"location":"ecolyo/project_architecture/environments/","text":"Environments We have 2 environments available for this project: - One environment of dev hosted on scaleway and managed by the dev team - One environment of production hosted on Cozy and managed by Cozy Dev environment aka alpha The dev environnment has been mounted on a dedicated instance on scaleway. Access to the dev environment You need to install an ssh tool like Putty or MobaXterm in order to connect to the server. Connection to the server is made using ssh key, you need to generate your own and ask administrator to allow your ssh key. Once done, you shoul be able to connect to the server using your private key. Cozy stack It is based on the easy-cozy project available on GitLab: https://forge.grandlyon.com/pocs/cozy/easy-cozy On the server, the .env file has been initialize with the good secrets (see the .env.template) and also initialize to create instance with Ecolyo and the 3 needed konnectors by default. This project will build and run 3 images: - the cozy stack - the couch db - keycloack To run the project please refer to the documentation on the GitLab project. Once the project is up and running, we are able to create, update and delete instances. Let's see more details in the dedicated section . Proxy Konnector for Ecolyo need proxy for the Oauth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy The proxy is written in Go language. The \"main.go\" file containt all the source code and also the default variables. Default variables are the one used for the dev environment but we will overwrite them for the production. To Launch the proxy, just pull the project and use the docker-compose file with following commands: git pull https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy cd cozy-oauth-proxy docker-compose up -d Ecolyo and konnectors By default the version present on the \"build-dev\" branch is used to install Ecolyo app and konnectors on a new instance. Some scripts has been created in order to install, update, downgrade, remove app and konnectors. Please refer to the dedicated section for more information. Prod environment This environment is fully managed by Cozy team. Cozy stack Fully managed by Cozy team. Proxy A dedicated proxy is deployed on Cozy side to allow konnector to make the Oauth dance. The proxy deployed is based on the project available on the GitLab but variables are overwritten using flags by the Cozy team in order to fit to the environment. For each modification in production, it needs: - to be done on the gitLab project - to be testeded in dev environnment After that we should ask Cozy to pull the modification from the GitLab in order to have them in production. Ecolyo and konnectors The production environment is based on the build branch which should reflect the build of sources present on master branch. Each deployment is done manually for each app/konnector by: - building the application (yarn build) - deploy the build on the build branch (yarn deploy) - publishing content of build branch into Cozy repository (yarn cozyPublish) Once it is published, Cozy team should validate it before deploying the new app version into all Cozy Grand Lyon instances.","title":"Environments"},{"location":"ecolyo/project_architecture/environments/#environments","text":"We have 2 environments available for this project: - One environment of dev hosted on scaleway and managed by the dev team - One environment of production hosted on Cozy and managed by Cozy","title":"Environments"},{"location":"ecolyo/project_architecture/environments/#dev-environment-aka-alpha","text":"The dev environnment has been mounted on a dedicated instance on scaleway.","title":"Dev environment aka alpha"},{"location":"ecolyo/project_architecture/environments/#access-to-the-dev-environment","text":"You need to install an ssh tool like Putty or MobaXterm in order to connect to the server. Connection to the server is made using ssh key, you need to generate your own and ask administrator to allow your ssh key. Once done, you shoul be able to connect to the server using your private key.","title":"Access to the dev environment"},{"location":"ecolyo/project_architecture/environments/#cozy-stack","text":"It is based on the easy-cozy project available on GitLab: https://forge.grandlyon.com/pocs/cozy/easy-cozy On the server, the .env file has been initialize with the good secrets (see the .env.template) and also initialize to create instance with Ecolyo and the 3 needed konnectors by default. This project will build and run 3 images: - the cozy stack - the couch db - keycloack To run the project please refer to the documentation on the GitLab project. Once the project is up and running, we are able to create, update and delete instances. Let's see more details in the dedicated section .","title":"Cozy stack"},{"location":"ecolyo/project_architecture/environments/#proxy","text":"Konnector for Ecolyo need proxy for the Oauth dance. The proxy is also mounted on the same instance as the Cozy stack and based on the project available on GitLab: https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy The proxy is written in Go language. The \"main.go\" file containt all the source code and also the default variables. Default variables are the one used for the dev environment but we will overwrite them for the production. To Launch the proxy, just pull the project and use the docker-compose file with following commands: git pull https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy cd cozy-oauth-proxy docker-compose up -d","title":"Proxy"},{"location":"ecolyo/project_architecture/environments/#ecolyo-and-konnectors","text":"By default the version present on the \"build-dev\" branch is used to install Ecolyo app and konnectors on a new instance. Some scripts has been created in order to install, update, downgrade, remove app and konnectors. Please refer to the dedicated section for more information.","title":"Ecolyo and konnectors"},{"location":"ecolyo/project_architecture/environments/#prod-environment","text":"This environment is fully managed by Cozy team.","title":"Prod environment"},{"location":"ecolyo/project_architecture/environments/#cozy-stack_1","text":"Fully managed by Cozy team.","title":"Cozy stack"},{"location":"ecolyo/project_architecture/environments/#proxy_1","text":"A dedicated proxy is deployed on Cozy side to allow konnector to make the Oauth dance. The proxy deployed is based on the project available on the GitLab but variables are overwritten using flags by the Cozy team in order to fit to the environment. For each modification in production, it needs: - to be done on the gitLab project - to be testeded in dev environnment After that we should ask Cozy to pull the modification from the GitLab in order to have them in production.","title":"Proxy"},{"location":"ecolyo/project_architecture/environments/#ecolyo-and-konnectors_1","text":"The production environment is based on the build branch which should reflect the build of sources present on master branch. Each deployment is done manually for each app/konnector by: - building the application (yarn build) - deploy the build on the build branch (yarn deploy) - publishing content of build branch into Cozy repository (yarn cozyPublish) Once it is published, Cozy team should validate it before deploying the new app version into all Cozy Grand Lyon instances.","title":"Ecolyo and konnectors"},{"location":"ecolyo/project_architecture/libraries/","text":"Libraries For this project, we use the libraries below: React Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM React Redux It is a predictable state container. It is implemented for a better management of the states because it allows to centralize all the states and the logic of the application. It lets a react component read data from a Redux store, and dispatch actions to the store to update data. Axios HTTP client library It allows to send HTTP request and manage the responses. Lodash javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions Moment Date library to parse, validate, manipulate, and display dates and times in JavaScript. Luxon Wrapper for Javascript dates and times. Jest Testing library It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product. Enzyme Testing utility for React It makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output. Sass CSS Preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations. Material UI It allows to create react component that implements Google's material design D3 It allows to manipulate documents based on data. It combines visualization components and a data-driven approach to DOM manipulation. React-swipeable-views It is a React component to make swipeable views React-lottie Lottie Animation View for React. It allows app to use animations easily. Husky It is used to improve your commit.","title":"Libraries"},{"location":"ecolyo/project_architecture/libraries/#libraries","text":"For this project, we use the libraries below:","title":"Libraries"},{"location":"ecolyo/project_architecture/libraries/#react","text":"Library to create user interfaces. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM","title":"React"},{"location":"ecolyo/project_architecture/libraries/#react-redux","text":"It is a predictable state container. It is implemented for a better management of the states because it allows to centralize all the states and the logic of the application. It lets a react component read data from a Redux store, and dispatch actions to the store to update data.","title":"React Redux"},{"location":"ecolyo/project_architecture/libraries/#axios","text":"HTTP client library It allows to send HTTP request and manage the responses.","title":"Axios"},{"location":"ecolyo/project_architecture/libraries/#lodash","text":"javascript utility library Lodash'modular method are great for: Iterating arrays, objects, & strings Manipulating & testing values Creating composite functions","title":"Lodash"},{"location":"ecolyo/project_architecture/libraries/#moment","text":"Date library to parse, validate, manipulate, and display dates and times in JavaScript.","title":"Moment"},{"location":"ecolyo/project_architecture/libraries/#luxon","text":"Wrapper for Javascript dates and times.","title":"Luxon"},{"location":"ecolyo/project_architecture/libraries/#jest","text":"Testing library It allows to evaluate functionalities of an app to ensure that the product is defect-free in order to produce the quality product.","title":"Jest"},{"location":"ecolyo/project_architecture/libraries/#enzyme","text":"Testing utility for React It makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.","title":"Enzyme"},{"location":"ecolyo/project_architecture/libraries/#sass","text":"CSS Preprocessor It allows us to easily manage large CSS files and split across different files. It allows us to create variables, nested rules, mixins, functions, and do mathematical calculations.","title":"Sass"},{"location":"ecolyo/project_architecture/libraries/#material-ui","text":"It allows to create react component that implements Google's material design","title":"Material UI"},{"location":"ecolyo/project_architecture/libraries/#d3","text":"It allows to manipulate documents based on data. It combines visualization components and a data-driven approach to DOM manipulation.","title":"D3"},{"location":"ecolyo/project_architecture/libraries/#react-swipeable-views","text":"It is a React component to make swipeable views","title":"React-swipeable-views"},{"location":"ecolyo/project_architecture/libraries/#react-lottie","text":"Lottie Animation View for React. It allows app to use animations easily.","title":"React-lottie"},{"location":"ecolyo/project_architecture/libraries/#husky","text":"It is used to improve your commit.","title":"Husky"},{"location":"ecolyo/project_architecture/remote_doctypes/","text":"Creation of the remote doctype The remote doctype should be created in the cozy repository : https://github.com/cozy/cozy-doctypes Remote doctype org.ecolyo.usage To create the remote the first create a folder named 'org.ecolyo.usage' and then add a file named request in the folder. Here is the structure of the file: POST https://API_URL Content-Type: application/json {{ data }} Local remote doctype As the doctype is not yet avaible on cozy repository, we first need to test it on local. For that we can use the \u2014doctypes command in the cozy-stack serve and use it to point to a local repository. Here are the step: clone the repository and add it in the ecolyo repository create the remote doctype. Here we create a new folder named 'org.ecolyo.usage' and add the following request file (replace API_URL by the url of the API): POST https://API_URL Content-Type: application/json {{ data }} add the \u2014doctypes command in the \"docker/cozy-app-dev-with-app.sh\" file and also the -remote-allow-custom-port flag ${ COZY_STACK_PATH } serve --allow-root \\ --appdir \" ${ appdir } \" \\ --host \"::\" \\ --port \" ${ COZY_STACK_PORT } \" \\ --admin-port \" ${ COZY_STACK_ADMIN_PORT } \" \\ --couchdb-url \" ${ COUCHDB_URL } \" \\ --doctypes /data/cozy-doctypes \\ --mail-port 1025 \\ --mail-disable-tls \\ --remote-allow-custom-port \\ --fs-url \"file://localhost ${ vfsdir } \" & add the following content in \"docker/disableCSP.yaml\": remote_assets : ecolyo-usage : http://cozy.tools:8080/remote/org.ecolyo.usage/ Go to the docker folder in the project root cd docker build the docker image and tag it to registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env : docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env Then add the following command to winstack script in the package.json: -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: docker-compose up Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): \"request\" : \"POST https://API_URL\\nContent-Type: application/json\\n\\n{{data}}\" , Use of remote doctype in the application Add permission in manifest.webapp \"ecolyo-usage\" : { \"type\" : \"org.ecolyo.usage\" , \"verbs\" : [ \"GET\" , \"POST\" ] } Don't forget to add the description Call the remote docType: const result = await client .getStackClient() .fetchJSON('POST', '/remote/org.ecolyo.usage', { JSON.stringify(indicator), }) Passing parameters to a remote doctype In order to pass parameters to a remote doctypes such as query paramaters or headers, you need to process the following way : You can pass header directly under the URL in the request file, such as Authorization or Content-Type headers. GET https://API_URL/?q ={ queryParam } Authorization: Bearer {{ secret_token }} Content-Type: application/json When you call the remote doctype, you can directly pass the parameters to the doctype : const result = await client .getStackClient() .fetchJSON(\"GET\", \"/remote/org.ecolyo.usage/queryParam=yourParameter\"); If you wanna know more about remote doctypes and how to store and use secret tokens, please refer to the official cozy documentation. Add secrets to a remote As above, you can pass a {{secret_token}} to your remote doctype. In local, you can directly pass it as a request param in io.cozy.doctypes/org.ecolyo.usage . Otherwise, you will have to add it in the shell script easy-cozy/db-init.sh on the server. You can add the following line to the file in order to add the secret in the database : docker-compose exec db curl -X PUT -d \"{\\\"_id\\\":\\\"org.ecolyo.dju\\\",\\\"token\\\":\\\"${API_DATAGRANDLYON_TOKEN}\\\"}\" http://127.0.0.1:5984/secrets%2Fio-cozy-remote-secrets/org.ecolyo.dju Make sure you have the right remote doctype name as _id. Then, in the .env file, just add your token variable.","title":"Remote Doctypes"},{"location":"ecolyo/project_architecture/remote_doctypes/#creation-of-the-remote-doctype","text":"The remote doctype should be created in the cozy repository : https://github.com/cozy/cozy-doctypes","title":"Creation of the remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#remote-doctype-orgecolyousage","text":"To create the remote the first create a folder named 'org.ecolyo.usage' and then add a file named request in the folder. Here is the structure of the file: POST https://API_URL Content-Type: application/json {{ data }}","title":"Remote doctype org.ecolyo.usage"},{"location":"ecolyo/project_architecture/remote_doctypes/#local-remote-doctype","text":"As the doctype is not yet avaible on cozy repository, we first need to test it on local. For that we can use the \u2014doctypes command in the cozy-stack serve and use it to point to a local repository. Here are the step: clone the repository and add it in the ecolyo repository create the remote doctype. Here we create a new folder named 'org.ecolyo.usage' and add the following request file (replace API_URL by the url of the API): POST https://API_URL Content-Type: application/json {{ data }} add the \u2014doctypes command in the \"docker/cozy-app-dev-with-app.sh\" file and also the -remote-allow-custom-port flag ${ COZY_STACK_PATH } serve --allow-root \\ --appdir \" ${ appdir } \" \\ --host \"::\" \\ --port \" ${ COZY_STACK_PORT } \" \\ --admin-port \" ${ COZY_STACK_ADMIN_PORT } \" \\ --couchdb-url \" ${ COUCHDB_URL } \" \\ --doctypes /data/cozy-doctypes \\ --mail-port 1025 \\ --mail-disable-tls \\ --remote-allow-custom-port \\ --fs-url \"file://localhost ${ vfsdir } \" & add the following content in \"docker/disableCSP.yaml\": remote_assets : ecolyo-usage : http://cozy.tools:8080/remote/org.ecolyo.usage/ Go to the docker folder in the project root cd docker build the docker image and tag it to registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env : docker build . -t registry.forge.grandlyon.com/web-et-numerique/llle_project/ecolyo/cozy-env Then add the following command to winstack script in the package.json: -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: docker-compose up Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): \"request\" : \"POST https://API_URL\\nContent-Type: application/json\\n\\n{{data}}\" ,","title":"Local remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#use-of-remote-doctype-in-the-application","text":"Add permission in manifest.webapp \"ecolyo-usage\" : { \"type\" : \"org.ecolyo.usage\" , \"verbs\" : [ \"GET\" , \"POST\" ] } Don't forget to add the description Call the remote docType: const result = await client .getStackClient() .fetchJSON('POST', '/remote/org.ecolyo.usage', { JSON.stringify(indicator), })","title":"Use of remote doctype in the application"},{"location":"ecolyo/project_architecture/remote_doctypes/#passing-parameters-to-a-remote-doctype","text":"In order to pass parameters to a remote doctypes such as query paramaters or headers, you need to process the following way : You can pass header directly under the URL in the request file, such as Authorization or Content-Type headers. GET https://API_URL/?q ={ queryParam } Authorization: Bearer {{ secret_token }} Content-Type: application/json When you call the remote doctype, you can directly pass the parameters to the doctype : const result = await client .getStackClient() .fetchJSON(\"GET\", \"/remote/org.ecolyo.usage/queryParam=yourParameter\"); If you wanna know more about remote doctypes and how to store and use secret tokens, please refer to the official cozy documentation.","title":"Passing parameters to a remote doctype"},{"location":"ecolyo/project_architecture/remote_doctypes/#add-secrets-to-a-remote","text":"As above, you can pass a {{secret_token}} to your remote doctype. In local, you can directly pass it as a request param in io.cozy.doctypes/org.ecolyo.usage . Otherwise, you will have to add it in the shell script easy-cozy/db-init.sh on the server. You can add the following line to the file in order to add the secret in the database : docker-compose exec db curl -X PUT -d \"{\\\"_id\\\":\\\"org.ecolyo.dju\\\",\\\"token\\\":\\\"${API_DATAGRANDLYON_TOKEN}\\\"}\" http://127.0.0.1:5984/secrets%2Fio-cozy-remote-secrets/org.ecolyo.dju Make sure you have the right remote doctype name as _id. Then, in the .env file, just add your token variable.","title":"Add secrets to a remote"},{"location":"ecolyo/services/","text":"In order to build an automated task within our cozy-stack, we can create services which are javascript files called from a trigger job. For instance on Ecolyo, to schedule a mail that alert the user that a new monthly report is available in the application, we add a trigger that is launched every month with a cron attribute. On that trigger we link a .js script then we instantiate this script with cozy-client. Configuration Manifest The service should be described in the manifest.webapp file. it should defined the type, the file and the trigger. See more information in the official doc of Cozy here Here is an example of service declaration in the ecolyo manifest: File location is determined after the build, see here . Cron See the cron definition at cozy-stack . Ecolyo services Service code are located under src\\targets\\services .","title":"Description"},{"location":"ecolyo/services/#configuration","text":"","title":"Configuration"},{"location":"ecolyo/services/#manifest","text":"The service should be described in the manifest.webapp file. it should defined the type, the file and the trigger. See more information in the official doc of Cozy here Here is an example of service declaration in the ecolyo manifest: File location is determined after the build, see here . Cron See the cron definition at cozy-stack .","title":"Manifest"},{"location":"ecolyo/services/#ecolyo-services","text":"Service code are located under src\\targets\\services .","title":"Ecolyo services"},{"location":"ecolyo/services/aggregator_usage_events/","text":"Definition of the service The service will run each day at [TO BE DEFINED], as defined in the manifest: \"aggregatorUsageEvents\": { \"type\": \"node\", \"file\": \"services/aggregatorUsageEvents/ecolyo.js\", \"trigger\": \"[TO BE DEFINED]\" } Main responsibilities of the service The service is responsible of : Collecting all new events from the com.grandlyon.ecolyo.usageevents Aggregated them to indicators Send indicators to the remote doctype To do As the remote doctype is not yet available for the service here are the remaining task to do: In the manifest.webapp: Declare the remote doctype (see here)[/ecolyo/project_architecture/remote_doctypes.md] Define the cron to run every day: to check with cozy to ensure that all instances will not trigger the service at the same time Create the translation for \"fr\" and \"en\" In the service: Update the remote doctype name in the sendIndicator method Add a check on the environment to ensure that the service will not post information on the remote doctype when its comes for alpha instance","title":"Aggregator usage events"},{"location":"ecolyo/services/aggregator_usage_events/#definition-of-the-service","text":"The service will run each day at [TO BE DEFINED], as defined in the manifest: \"aggregatorUsageEvents\": { \"type\": \"node\", \"file\": \"services/aggregatorUsageEvents/ecolyo.js\", \"trigger\": \"[TO BE DEFINED]\" }","title":"Definition of the service"},{"location":"ecolyo/services/aggregator_usage_events/#main-responsibilities-of-the-service","text":"The service is responsible of : Collecting all new events from the com.grandlyon.ecolyo.usageevents Aggregated them to indicators Send indicators to the remote doctype","title":"Main responsibilities of the service"},{"location":"ecolyo/services/aggregator_usage_events/#to-do","text":"As the remote doctype is not yet available for the service here are the remaining task to do: In the manifest.webapp: Declare the remote doctype (see here)[/ecolyo/project_architecture/remote_doctypes.md] Define the cron to run every day: to check with cozy to ensure that all instances will not trigger the service at the same time Create the translation for \"fr\" and \"en\" In the service: Update the remote doctype name in the sendIndicator method Add a check on the environment to ensure that the service will not post information on the remote doctype when its comes for alpha instance","title":"To do"},{"location":"ecolyo/services/consumption_alert/","text":"Definition of the service The service will run everyday at 10.00 am, as defined in the manifest: \"consumptionAlert\": { \"type\": \"node\", \"file\": \"services/consumptionAlert/ecolyo.js\", \"trigger\": \"@cron 0 3 * * *\" } Main responsibilities of the service The service is responsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel). For now it only monitors water consumptions. Main steps are the following: - Check the \"sendConsumptionAlert\" and \"waterDailyConsumptionLimit\" attributes in the com.grandlyon.ecolyo.profile doctype. If \"sendConsumptionAlert\" is set to true and \"waterDailyConsumptionLimit\" is not set to 0, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url, consumption of the last day fetched by the egl konnector). - Check that the last consumption is greater than the limit set by the user. If false the service will stop. - Build the mail. - Send the mail. Sending mail Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Consumption Alert"},{"location":"ecolyo/services/consumption_alert/#definition-of-the-service","text":"The service will run everyday at 10.00 am, as defined in the manifest: \"consumptionAlert\": { \"type\": \"node\", \"file\": \"services/consumptionAlert/ecolyo.js\", \"trigger\": \"@cron 0 3 * * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/consumption_alert/#main-responsibilities-of-the-service","text":"The service is responsible of sending a mail to user to warn him about an overload in his fluid consumption (based on a limit the user fixed in the option panel). For now it only monitors water consumptions. Main steps are the following: - Check the \"sendConsumptionAlert\" and \"waterDailyConsumptionLimit\" attributes in the com.grandlyon.ecolyo.profile doctype. If \"sendConsumptionAlert\" is set to true and \"waterDailyConsumptionLimit\" is not set to 0, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url, consumption of the last day fetched by the egl konnector). - Check that the last consumption is greater than the limit set by the user. If false the service will stop. - Build the mail. - Send the mail.","title":"Main responsibilities of the service"},{"location":"ecolyo/services/consumption_alert/#sending-mail","text":"Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Sending mail"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/","text":"Definition of the service The service will run everyday 3rd of month at 8.00 am, as defined in the manifest: \"enedisHalfHourMonthlyAnalysis\": { \"type\": \"node\", \"file\": \"services/enedisHalfHourMonthlyAnalysis/ecolyo.js\", \"trigger\": \"@cron 0 0 8 3 * *\" } Main responsibilities of the service The service is responsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype com.grandlyon.enedis.monthly.analysis.data Main steps are the following : Check com.grandlyon.enedis.minute doctype. If the doctype contains entries, it means the half-hour consumption tracking has been activated, and there is data to use. If there is half-hour data, creates the average consumption load for the last month (for the analysis) and store it in the doctype com.grandlyon.enedis.monthly.analysis.data Checks if there is other entries in this doctype, if so, it means the service has already run before, so we create and store enedis monthly analysis for every month between the first entry in the enedis.minute doctype and the first entry in the enedis.monthly.analysis doctype. This way we will have an analysis available until the first month the half-hour consumption tracking has been activated If there is no other entries in this doctype, it means it is the first the service runs, so we create and store enedis analysis from the last month analysis and until the minimum date between 1 year ago and the the date of first enedis.minute doctype entry. Calculating the average half-hour consumption In order to calculate the average half-hour consumption on a given month, we use the function getEnedisMonthAnalysisData which takes the cozy client , a month and a year in parameters. This function is charged to do the following things : Get the graph data for the chosen month on the given month period. For each day, get the half-hour consumption Filter days in 2 parts : weekdays and week end days For each half-hour data push the data in a global 2 dimensional array ; there is 2 global array, one for week-end days and the other for weekdays At the point we have 2 global array with each 48 arrays filled with the corresponding values. To illustrate this, here is an example of how the data is sorted : weekEndValuesArray : [ 8h-8h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 8h30-9h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 9h-9h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ... 23h30-00h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ] - Once the array is filled with all available values, we just have to calculate the average for each half-hour step The minimum value is calculated by the getMonthMinLoad function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplied by 48 (the number of half hour entries in a day) and with the number of days in the month. The maxpower value is fetched from the doctype com.grandlyon.enedis.maxpower , the value is stored on a daily basis, so take the maximum value for the given month. The result is stored in com.grandlyon.enedis.monthly.analysis.data according to the following model : EnedisMonthlyAnalysisData { weekDaysHalfHourAverageValues: number[] weekEndDaysHalfHourAverageValues: number[] minimumLoad: number maxpower: number month: number year: number } Important rules The empty half-hour values represented by a \"-1\" are not pushed in the valuesArray so we can keep an accurate average We have no choice but to get the half-hour values day per day because cozy limits the request result number to 1000 entries, and it is not enough to get a maximum of 48*31= 1488 entries per month, plus it doesn't allows us to properly calculate and average and handle the empty values. This service is quite long to run so we decided to run it 2 hours before the newsletter sending, this way user can acces his last enedis analysis once he received the newsletter.","title":"Enedis Halfhour Monthly Analysis"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#definition-of-the-service","text":"The service will run everyday 3rd of month at 8.00 am, as defined in the manifest: \"enedisHalfHourMonthlyAnalysis\": { \"type\": \"node\", \"file\": \"services/enedisHalfHourMonthlyAnalysis/ecolyo.js\", \"trigger\": \"@cron 0 0 8 3 * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#main-responsibilities-of-the-service","text":"The service is responsible of calculating the average consumption load for half hour timestep on a given month. It is exclusively for Electricity fluid. The data result is stored in the doctype com.grandlyon.enedis.monthly.analysis.data Main steps are the following : Check com.grandlyon.enedis.minute doctype. If the doctype contains entries, it means the half-hour consumption tracking has been activated, and there is data to use. If there is half-hour data, creates the average consumption load for the last month (for the analysis) and store it in the doctype com.grandlyon.enedis.monthly.analysis.data Checks if there is other entries in this doctype, if so, it means the service has already run before, so we create and store enedis monthly analysis for every month between the first entry in the enedis.minute doctype and the first entry in the enedis.monthly.analysis doctype. This way we will have an analysis available until the first month the half-hour consumption tracking has been activated If there is no other entries in this doctype, it means it is the first the service runs, so we create and store enedis analysis from the last month analysis and until the minimum date between 1 year ago and the the date of first enedis.minute doctype entry.","title":"Main responsibilities of the service"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#calculating-the-average-half-hour-consumption","text":"In order to calculate the average half-hour consumption on a given month, we use the function getEnedisMonthAnalysisData which takes the cozy client , a month and a year in parameters. This function is charged to do the following things : Get the graph data for the chosen month on the given month period. For each day, get the half-hour consumption Filter days in 2 parts : weekdays and week end days For each half-hour data push the data in a global 2 dimensional array ; there is 2 global array, one for week-end days and the other for weekdays At the point we have 2 global array with each 48 arrays filled with the corresponding values. To illustrate this, here is an example of how the data is sorted : weekEndValuesArray : [ 8h-8h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 8h30-9h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] 9h-9h30 : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ... 23h30-00h : [day1Value, day2Value, day3value ..... lastWeekEndDayValue] ] - Once the array is filled with all available values, we just have to calculate the average for each half-hour step The minimum value is calculated by the getMonthMinLoad function, it takes the complete week and weekend values arrays as parameters and return the minimum value, excluding -1 (empty values), and 0 (null values). This value is multiplied by 48 (the number of half hour entries in a day) and with the number of days in the month. The maxpower value is fetched from the doctype com.grandlyon.enedis.maxpower , the value is stored on a daily basis, so take the maximum value for the given month. The result is stored in com.grandlyon.enedis.monthly.analysis.data according to the following model : EnedisMonthlyAnalysisData { weekDaysHalfHourAverageValues: number[] weekEndDaysHalfHourAverageValues: number[] minimumLoad: number maxpower: number month: number year: number }","title":"Calculating the average half-hour consumption"},{"location":"ecolyo/services/enedis_halfhour_monthly_analysis/#important-rules","text":"The empty half-hour values represented by a \"-1\" are not pushed in the valuesArray so we can keep an accurate average We have no choice but to get the half-hour values day per day because cozy limits the request result number to 1000 entries, and it is not enough to get a maximum of 48*31= 1488 entries per month, plus it doesn't allows us to properly calculate and average and handle the empty values. This service is quite long to run so we decided to run it 2 hours before the newsletter sending, this way user can acces his last enedis analysis once he received the newsletter.","title":"Important rules"},{"location":"ecolyo/services/monthly_report_notification/","text":"Definition of the service The service will run the 3rd of each month at 10.00 am, as defined in the manifest: \"monthlyReportNotification\": { \"type\": \"node\", \"file\": \"services/monthlyReportNotification/ecolyo.js\", \"trigger\": \"@cron 0 0 10 3 * *\" } Main responsibilities of the service The service is responsible of sending a mail to user to warn him about the availability of a new information in the Analyse. Main steps are the following: - Check the \"sendReportNotification\" attribute in the com.grandlyon.ecolyo.profile doctype. If true, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url). - Build the mail. - Send the mail. Sending mail Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Monthly report notification"},{"location":"ecolyo/services/monthly_report_notification/#definition-of-the-service","text":"The service will run the 3rd of each month at 10.00 am, as defined in the manifest: \"monthlyReportNotification\": { \"type\": \"node\", \"file\": \"services/monthlyReportNotification/ecolyo.js\", \"trigger\": \"@cron 0 0 10 3 * *\" }","title":"Definition of the service"},{"location":"ecolyo/services/monthly_report_notification/#main-responsibilities-of-the-service","text":"The service is responsible of sending a mail to user to warn him about the availability of a new information in the Analyse. Main steps are the following: - Check the \"sendReportNotification\" attribute in the com.grandlyon.ecolyo.profile doctype. If true, service will continue, else it will stop. - Fetches metadata to customize the mail (Public name, instance url). - Build the mail. - Send the mail.","title":"Main responsibilities of the service"},{"location":"ecolyo/services/monthly_report_notification/#sending-mail","text":"Doc of cozy for sendmail worker: https://docs.cozy.io/en/cozy-stack/workers/#sendmail-worker Send In local you can use the mail hog tools to see the mail sent by the stack using http://cozy.tools:8025/","title":"Sending mail"},{"location":"konnectors/","text":"Konnectors are scripts that import data from a web service and put those data into cozy. Each konnector is an independant application managed by the cozy home application. Ecolyo uses data from 3 web services : Enedis Grdf Eau du grand lyon (EGL) All the konnectors are configured to retrieve user's data as far as 3 years back. Some variation have to be considered : When the user launches the konnector manually, it fetches 1 year of data (in order to reduce running time). When a konnector is launched by the cozy stack (at a random time between 10am and 11am), it fetches 3 years of data. When a konnector retrieves a load at the half-hour timeline (ex: enedis), it fetches back to 4 weeks.","title":"Introduction"},{"location":"konnectors/egl/","text":"EGL Konnector This konnector fetches consumptions measures from EGL API. The EGL API allows us to get a user's consumption data gathered by it's connected water meter \"T\u00e9l\u00e9o\". You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ API Url for Development : https://agence-rec.eaudugrandlyon.com API Url for Production : https://agence.eaudugrandlyon.com/ws Authentication In order to authenticate to the EGL API we have to request the following route Method : POST Authentication Route : /connect.asp \"headers\" : { { \"AuthKey\" : <your - au t h - key> , \"Content-Type\" : \"application/x-www-form-urlencoded\" } } \"body\" : { \"mode\" : \"formdata\" { \"login\" : <your - logi n > , \"pass\" : <your - password> } } Once you've sent this request the API should answer with a code 100 if everything is ok and provides you a valid token and num_abt that you will use later in order to get data. { \"codeRetour\" : 100 , \"libelleRetour\" : \"Connect\u00e9\" , \"resultatRetour\" : { \"num_abt\" : t o t o , \"list_num_abt\" : [ t o t o , tata ] \"token\" : \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\" } } Fetch Data In order to get data from the EGL API we have to request the following route : Method : POST Data Route : /getAllAgregatsByAbonnement.aspx \"body\" : { \"mode\" : \"formdata\" { \"token\" : \"897555754A703055397897456568776E32704C3953514F5R\" , \"num_abt\" : 1895683 , \"date_debut\" : MM/JJ/YYYY , \"date_fin\" : MM/JJ/YYYY } } The dates must be valid dates otherwise you'll get an error The answer will provide you an array of data day by day with the value got by the water meter 'ValeurIndex' at this moment. { \"codeRetour\" : 100 , \"libelleRetour\" : \"L'op\u00e9ration a r\u00e9ussi\" , \"resultatRetour\" : [ { \"DateReleve\" : \"2020-07-01T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562362 }, { \"DateReleve\" : \"2020-07-02T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562432 } ] } Daily data is calculated by substracting current valeurIndex day with previous day. TypeAgregats \"R\" means the real value \"A\" means an anomaly \"D\" means a water meter changing \"V\" means data has been estimated on a period \"X\" marks the start and end of \"V\" estimated data \"T\" means pending data If you're looking for more information about the API, checkout the complete API documentation Konnector Methods Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data authenticate Authentication method. Requires login, password, baseUrl and ApiAuthKey. storeData Save data in the right doctype db and prevent duplicated keys format Format data for DB storage and remove bad data (former \"T\" typeagregats remain in response even if the data was added later, leading to duplicated data) resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.egl.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after egl data reprocess","title":"Eau du Grand Lyon"},{"location":"konnectors/egl/#egl-konnector","text":"This konnector fetches consumptions measures from EGL API. The EGL API allows us to get a user's consumption data gathered by it's connected water meter \"T\u00e9l\u00e9o\". You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ API Url for Development : https://agence-rec.eaudugrandlyon.com API Url for Production : https://agence.eaudugrandlyon.com/ws","title":"EGL Konnector"},{"location":"konnectors/egl/#authentication","text":"In order to authenticate to the EGL API we have to request the following route Method : POST Authentication Route : /connect.asp \"headers\" : { { \"AuthKey\" : <your - au t h - key> , \"Content-Type\" : \"application/x-www-form-urlencoded\" } } \"body\" : { \"mode\" : \"formdata\" { \"login\" : <your - logi n > , \"pass\" : <your - password> } } Once you've sent this request the API should answer with a code 100 if everything is ok and provides you a valid token and num_abt that you will use later in order to get data. { \"codeRetour\" : 100 , \"libelleRetour\" : \"Connect\u00e9\" , \"resultatRetour\" : { \"num_abt\" : t o t o , \"list_num_abt\" : [ t o t o , tata ] \"token\" : \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\" } }","title":"Authentication"},{"location":"konnectors/egl/#fetch-data","text":"In order to get data from the EGL API we have to request the following route : Method : POST Data Route : /getAllAgregatsByAbonnement.aspx \"body\" : { \"mode\" : \"formdata\" { \"token\" : \"897555754A703055397897456568776E32704C3953514F5R\" , \"num_abt\" : 1895683 , \"date_debut\" : MM/JJ/YYYY , \"date_fin\" : MM/JJ/YYYY } } The dates must be valid dates otherwise you'll get an error The answer will provide you an array of data day by day with the value got by the water meter 'ValeurIndex' at this moment. { \"codeRetour\" : 100 , \"libelleRetour\" : \"L'op\u00e9ration a r\u00e9ussi\" , \"resultatRetour\" : [ { \"DateReleve\" : \"2020-07-01T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562362 }, { \"DateReleve\" : \"2020-07-02T00:00:00+02:00\" , \"TypeAgregat\" : \"R\" , \"ValeurIndex\" : 562432 } ] } Daily data is calculated by substracting current valeurIndex day with previous day.","title":"Fetch Data"},{"location":"konnectors/egl/#typeagregats","text":"\"R\" means the real value \"A\" means an anomaly \"D\" means a water meter changing \"V\" means data has been estimated on a period \"X\" marks the start and end of \"V\" estimated data \"T\" means pending data If you're looking for more information about the API, checkout the complete API documentation","title":"TypeAgregats"},{"location":"konnectors/egl/#konnector-methods","text":"Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data authenticate Authentication method. Requires login, password, baseUrl and ApiAuthKey. storeData Save data in the right doctype db and prevent duplicated keys format Format data for DB storage and remove bad data (former \"T\" typeagregats remain in response even if the data was added later, leading to duplicated data) resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.egl.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after egl data reprocess","title":"Konnector Methods"},{"location":"konnectors/enedis/","text":"This konnector fetches consumptions measures from Enedis API. This is an Oauth Konnector, meaning the authentication performed to access all data is made following an Oauth2 protocol. You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ https://docs.cozy.io/en/tutorials/konnector/oauth/ Enedis Konnector The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentication. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the usage_point_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, if no usage_point_id are found in database or fields then proceed as a first launch. Store the usage_point_id in oauth_callback_result in db (see addData ). Konnector finds usage point_id when starting but token is expired. Proceed to refresh token and restart konnector with usage_point_id in fields params (see _Troubleshooting when asking for refresh token section at the end of the page). Enedis API API Url for Production : https://gw.prd.api.enedis.fr API url for Development : https://gw.hml.api.enedis.fr Once you've finished the Oauth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo: Method : GET Route : /v4/metering_data/consumption_load_curve Method : GET Route : /v4/metering_data/daily_consumption Method : GET Route : /v4/metering_data/daily_consumption_max_power \"params\" : { \"usage_point_id\" : <your - usage - poi nt - id> , \"start\" : \"YYYY-MM-DD\" , \"end\" : \"YYYY-MM-DD\" , } \"headers\" : { \"Accept\" : \"application/json\" , \"Authorization\" : \"Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } For more information about Datahub-Enedis API, checkout the Datahub documentation . Konnector Methods Method Description start Init Function getDailyData Retrieve data from the API. Format: { value: \"Wh\", \"date\": \"YYYY-MM-DD\" } \" startLoadDataProcess Check if history is loaded. If not, call several time the api to retrieve 1 month of history for load data. If yes only call once the api launchLoadDataProcess Launch process to handle load data getLoadData Retrieve data from the API. Format: { value: \"W\", \"date\": \"YYYY-MM-DD hh:mm:ss\" } processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data aggregateMonthAndYearData Aggregate data from daily data to monthly and yearly data aggregateHourlyData Aggregate data from load data (every 30 min) to Hourly data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAggregatedData Retrieve and remove old data for a specific doctype and return an array of aggregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" getMaxPower Retrieve data from the maxpower API. Format: { value: \"kVA\", \"date\": \"YYYY-MM-DD\" } isHistoryLoaded Function checking if the history is loaded resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.enedis.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after enedis data reprocess Troubleshooting when asking for refresh token When a token expires, the konnector will encounter an error when fetching user data, leading to a refresh token request. Since refresh token requests restart the Konnector, it was decided to add the usage_point_id into the start fields when asking for a refresh token (see line 97). restart to refresh token Line 85: await cozyClient.fetchJSON( 'POST', `/accounts/enedisgrandlyon/${accountId}/refresh` ) Line 97: ```fields.usage_point_id = usage_point_id``` Line 98: ```return start(fields, cozyParameters, false)``` In fact the usage_point_id still remains in the account collection, but on restart, the konnector loses this._account context leading to an error when searching for usage_point_id in account. Half-hour data issue When requesting the load curve api while the half-hour data is not activated, we may have an error response 404 with a message \"no data found\", which makes the whole data fetching process crash. So instead of making it crash we just log this particular error and avoid the konnector to crash. So we added a condition in line 227, in the checkConsentForLoadCurve function : if ( (err.statusCode === 404 || err.code === 404) && err.message.search('no_data_found') > 0 ) { log('info', 'Handling half-hour error on connection') return false }","title":"Enedis"},{"location":"konnectors/enedis/#enedis-konnector","text":"The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentication. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the usage_point_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, if no usage_point_id are found in database or fields then proceed as a first launch. Store the usage_point_id in oauth_callback_result in db (see addData ). Konnector finds usage point_id when starting but token is expired. Proceed to refresh token and restart konnector with usage_point_id in fields params (see _Troubleshooting when asking for refresh token section at the end of the page).","title":"Enedis Konnector"},{"location":"konnectors/enedis/#enedis-api","text":"API Url for Production : https://gw.prd.api.enedis.fr API url for Development : https://gw.hml.api.enedis.fr Once you've finished the Oauth protocol and have a valid token, you can go fetch the data. Currently we use the two following endpoints in Ecolyo: Method : GET Route : /v4/metering_data/consumption_load_curve Method : GET Route : /v4/metering_data/daily_consumption Method : GET Route : /v4/metering_data/daily_consumption_max_power \"params\" : { \"usage_point_id\" : <your - usage - poi nt - id> , \"start\" : \"YYYY-MM-DD\" , \"end\" : \"YYYY-MM-DD\" , } \"headers\" : { \"Accept\" : \"application/json\" , \"Authorization\" : \"Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } For more information about Datahub-Enedis API, checkout the Datahub documentation .","title":"Enedis API"},{"location":"konnectors/enedis/#konnector-methods","text":"Method Description start Init Function getDailyData Retrieve data from the API. Format: { value: \"Wh\", \"date\": \"YYYY-MM-DD\" } \" startLoadDataProcess Check if history is loaded. If not, call several time the api to retrieve 1 month of history for load data. If yes only call once the api launchLoadDataProcess Launch process to handle load data getLoadData Retrieve data from the API. Format: { value: \"W\", \"date\": \"YYYY-MM-DD hh:mm:ss\" } processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data aggregateMonthAndYearData Aggregate data from daily data to monthly and yearly data aggregateHourlyData Aggregate data from load data (every 30 min) to Hourly data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAggregatedData Retrieve and remove old data for a specific doctype and return an array of aggregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" getMaxPower Retrieve data from the maxpower API. Format: { value: \"kVA\", \"date\": \"YYYY-MM-DD\" } isHistoryLoaded Function checking if the history is loaded resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.enedis.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after enedis data reprocess","title":"Konnector Methods"},{"location":"konnectors/enedis/#troubleshooting-when-asking-for-refresh-token","text":"When a token expires, the konnector will encounter an error when fetching user data, leading to a refresh token request. Since refresh token requests restart the Konnector, it was decided to add the usage_point_id into the start fields when asking for a refresh token (see line 97). restart to refresh token Line 85: await cozyClient.fetchJSON( 'POST', `/accounts/enedisgrandlyon/${accountId}/refresh` ) Line 97: ```fields.usage_point_id = usage_point_id``` Line 98: ```return start(fields, cozyParameters, false)``` In fact the usage_point_id still remains in the account collection, but on restart, the konnector loses this._account context leading to an error when searching for usage_point_id in account.","title":"Troubleshooting when asking for refresh token"},{"location":"konnectors/enedis/#half-hour-data-issue","text":"When requesting the load curve api while the half-hour data is not activated, we may have an error response 404 with a message \"no data found\", which makes the whole data fetching process crash. So instead of making it crash we just log this particular error and avoid the konnector to crash. So we added a condition in line 227, in the checkConsentForLoadCurve function : if ( (err.statusCode === 404 || err.code === 404) && err.message.search('no_data_found') > 0 ) { log('info', 'Handling half-hour error on connection') return false }","title":"Half-hour data issue"},{"location":"konnectors/grdf/","text":"This konnector fetches consumptions measures from Grdf Adict API. This is an Oauth Konnector, meaning the authentication performed to access all data is made following an Oauth2 protocol. You can clone the project here . You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started/ https://docs.cozy.io/en/tutorials/konnector/oauth/ Grdf Adict Konnector The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentication. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the pce_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, fails to find a pce_id in database on first launch therefore decodes the id_token to store the pce_id in db (see addData ). Konnector restarts, this time knowing a pce_id, it fails to fetch datas because the access_token from oauth call has a reduced scope (only scoping for meta data requests). Konnector launches a refresh call, the proxy knows to answer it with a client_credentials grant_type call to grdf /access_token. Konnector restarts with everyting needed in database to fetch datas and store them in couchdb. Further jobs will not need to change scope again and will only ask for refresh tokens. Konnector Flow summarized On delete account When deleting one's konnector account, src/onDeleteAccount.js is triggered. In order to facilitate a new oauth connection later on. It aims to remove user's consent between its grdf account and the Metropole de Lyon. To do so, we use the secret credentials stored in account_type grdfgrandlyon.delete (see cozy offical documentation to know how we create a special account_type secret) to generate an access_token with enough permission to revoke any consents given to the Metropole. Launch on standalone In the project repository type yarn standalone to launch the konnector without a cozy stack running. Installation Build the konnector with yarn build . Install on easy-cozy (development purposes) sudo docker cp /home/easy-cozy/fun/grdf-konnector/build/ $container_id:/tmp/grdf-oauth sudo docker-compose exec cozy ./cozy konnectors install grdf-oauth --domain \"$alphaDomain\" file:///tmp/grdf-oauth $container_id Install on production Type yarn deploy to build on a dedicated branch. Build branch is stored as a docker image in a registry : Container Registry . Konnector Methods Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAggregatedData Retrieve and remove old data for a specific doctype and return an array of aggregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.grdf.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after grdf data reprocess","title":"GRDF"},{"location":"konnectors/grdf/#grdf-adict-konnector","text":"The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the proxy documentation to fully understand all the interactions that will be told below. All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data. On its first launch, following the Oauth Client Connect authentication. The cozy stack calls the authentification_endpoint and start the oauth protocol, see proxy doc . The account has now an access_token and an id_token from the oauth call id token is only given when requesting the token endpoint in _authorization_code grant_type. This token holds several meta datas, including the pce_id (id of user's meter) that will be needed further to fetch user's datas. Konnector starts, fails to find a pce_id in database on first launch therefore decodes the id_token to store the pce_id in db (see addData ). Konnector restarts, this time knowing a pce_id, it fails to fetch datas because the access_token from oauth call has a reduced scope (only scoping for meta data requests). Konnector launches a refresh call, the proxy knows to answer it with a client_credentials grant_type call to grdf /access_token. Konnector restarts with everyting needed in database to fetch datas and store them in couchdb. Further jobs will not need to change scope again and will only ask for refresh tokens.","title":"Grdf Adict Konnector"},{"location":"konnectors/grdf/#konnector-flow-summarized","text":"","title":"Konnector Flow summarized"},{"location":"konnectors/grdf/#on-delete-account","text":"When deleting one's konnector account, src/onDeleteAccount.js is triggered. In order to facilitate a new oauth connection later on. It aims to remove user's consent between its grdf account and the Metropole de Lyon. To do so, we use the secret credentials stored in account_type grdfgrandlyon.delete (see cozy offical documentation to know how we create a special account_type secret) to generate an access_token with enough permission to revoke any consents given to the Metropole.","title":"On delete account"},{"location":"konnectors/grdf/#launch-on-standalone","text":"In the project repository type yarn standalone to launch the konnector without a cozy stack running.","title":"Launch on standalone"},{"location":"konnectors/grdf/#installation","text":"Build the konnector with yarn build .","title":"Installation"},{"location":"konnectors/grdf/#install-on-easy-cozy-development-purposes","text":"sudo docker cp /home/easy-cozy/fun/grdf-konnector/build/ $container_id:/tmp/grdf-oauth sudo docker-compose exec cozy ./cozy konnectors install grdf-oauth --domain \"$alphaDomain\" file:///tmp/grdf-oauth $container_id","title":"Install on easy-cozy (development purposes)"},{"location":"konnectors/grdf/#install-on-production","text":"Type yarn deploy to build on a dedicated branch. Build branch is stored as a docker image in a registry : Container Registry .","title":"Install on production"},{"location":"konnectors/grdf/#konnector-methods","text":"Method Description start Init Function getData Retrieve data from API processData Parse data. Remove existing data from DB using hydrateAndFilter, store filtered data and return the list of filtered data storeData Save data in the right doctype db and prevent duplicated keys formateData Format data for DB storage and remove bad data buildAggregatedData Retrieve and remove old data for a specific doctype and return an array of aggregated data buildDataFromKey Format an entry for DB storage using key and value. For year doctype: key = \"YYYY\". For month doctype: key = \"YYYY-MM\" resetInProgressAggregatedData Function handling special case.The temporary aggregated data need to be remove in order for the most recent one te be saved. Ex for com.grandlyon.grdf.year : { load: 76.712, year: 2020, ... } need to be replace by { load: 82.212, year: 2020, ... } after grdf data reprocess","title":"Konnector Methods"},{"location":"pilote/","text":"Pilote aims to help people in various administrative processes, allowing them to share their personal information with a social worker to build the best possible claim for every needs. Reminder If you're a new developer tasked to work on this project, please get acquainted with the team processes and read the advised dev environment documentation and the self-data prerequisites . Repositories global backend travailleur social front usager Acces to the application deployed DEV : https://pilote-agent-dev.grandlyon.com/ REC : https://pilote-agent-rec.grandlyon.com/ PROD : https://pilote-agent.grandlyon.com/","title":"Introduction"},{"location":"pilote/#repositories","text":"global backend travailleur social front usager","title":"Repositories"},{"location":"pilote/#acces-to-the-application-deployed","text":"DEV : https://pilote-agent-dev.grandlyon.com/ REC : https://pilote-agent-rec.grandlyon.com/ PROD : https://pilote-agent.grandlyon.com/","title":"Acces to the application deployed"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/application/deploy/","text":"Deployment For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline linked is running. On master branch, only build is set on the pipeline.","title":"Deploy"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/application/deploy/#deployment","text":"For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline linked is running. On master branch, only build is set on the pipeline.","title":"Deployment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/","text":"This section explains the different API route. Descriptions are not currently up-to-date. A swagger documentation can be consulted at http://localhost:3000/api/doc/ Auth api/auth/signin : It is used for local and dev authentication. It is linked to two different password into the database. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/token/check : It is used for check one token. It is called from cozy-stack service of the usager. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/login : It is used for Sign&Go authentication. Linked to AuthStrategy. login/callback : Get the authentication from Sign&Go process. Beneficiary /api/beneficiaire : Get all usager known from Postgre database. /api/beneficiaire/create' : This rotue is used in order to store Usager domain and his trigger proccess from Cozy. This route is protected by a COZY_SECRET env variable token. This token is generated by us. If you change it, you need to inform Cozy team because this token is store in their side also. /api/beneficiaire/remove' : This rotue is used in order to remove Usager domain and his trigger proccess. Only availabe by POST. This route is not accessible from any part of TS FRONT application. Protected rout by the same token of create route. Add one benificiary by Postman Create a POST request Entry the URL: http://localhost:3020/api/beneficiaire/create or https://pilote-agent-rec.grandlyon.com/api/beneficiaire/create Push in Authorizathion/ Bearer Token => the token use by \"process.env.COZY_SECRET\" In Body, as JSON format example : {\"cozy_name\":\"pilote-rec.cozy.self-data.alpha.grandlyon.com\",\"trigger\":\"https://pilote-rec.cozy.self-data.alpha.grandlyon.com/jobs/webhooks/d010bf3fa2aed6f3c6584ea93a54affc\"} Local : {\"cozy_name\":\"pilote.cozy.tools:8080\",\"trigger\":\"http://pilote.cozy.tools:8080/jobs/webhooks/\"} Cozy api/redirect/cozy : Allow to send information to the cozy-stack in order to run smsProccess on cozy-stask side. Users Authentication only used for local or dev environment because Sign&Go is only available for rec and prod env.","title":"Routes"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#auth","text":"api/auth/signin : It is used for local and dev authentication. It is linked to two different password into the database. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/token/check : It is used for check one token. It is called from cozy-stack service of the usager. api/auth/token : It is used for generate one token. Only for internal process. This route is not call from another apps. api/auth/login : It is used for Sign&Go authentication. Linked to AuthStrategy. login/callback : Get the authentication from Sign&Go process.","title":"Auth"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#beneficiary","text":"/api/beneficiaire : Get all usager known from Postgre database. /api/beneficiaire/create' : This rotue is used in order to store Usager domain and his trigger proccess from Cozy. This route is protected by a COZY_SECRET env variable token. This token is generated by us. If you change it, you need to inform Cozy team because this token is store in their side also. /api/beneficiaire/remove' : This rotue is used in order to remove Usager domain and his trigger proccess. Only availabe by POST. This route is not accessible from any part of TS FRONT application. Protected rout by the same token of create route.","title":"Beneficiary"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#add-one-benificiary-by-postman","text":"Create a POST request Entry the URL: http://localhost:3020/api/beneficiaire/create or https://pilote-agent-rec.grandlyon.com/api/beneficiaire/create Push in Authorizathion/ Bearer Token => the token use by \"process.env.COZY_SECRET\" In Body, as JSON format example : {\"cozy_name\":\"pilote-rec.cozy.self-data.alpha.grandlyon.com\",\"trigger\":\"https://pilote-rec.cozy.self-data.alpha.grandlyon.com/jobs/webhooks/d010bf3fa2aed6f3c6584ea93a54affc\"} Local : {\"cozy_name\":\"pilote.cozy.tools:8080\",\"trigger\":\"http://pilote.cozy.tools:8080/jobs/webhooks/\"}","title":"Add one benificiary by Postman"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#cozy","text":"api/redirect/cozy : Allow to send information to the cozy-stack in order to run smsProccess on cozy-stask side.","title":"Cozy"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/#users","text":"Authentication only used for local or dev environment because Sign&Go is only available for rec and prod env.","title":"Users"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial-back.git Installation of the project Start Pilote application To start Pilote application just launch the command in a Powershell or Windows Powershell tool: yarn docker:dev If the application starts successfully you should obtain two containers running: mps-travailleursocial-back_mps_1 mps-travailleursocial-back_postgres_1 You can access by: http://localhost:3020/api It will be redirect to the Swagger UI. It allow to test the different API defined. Run Jest test To start test defined just run the command in a Powershell or Windows Powershell tool: yarn test:watch Don't forget to uncomment ending row into beneficiary.service.ts file before to run the above command. Useful docker command build : docker build -t mps . run container : docker-compose -f docker-compose.yml up --remove-orphans access container db: docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres delete image/containers: docker system prune -a -f enter container: docker exec -it <id_container> bash remove container: docker container rm -f <id_container> Synapps environment check mps container : docker ps --filter \"name=mps\" or use this alias created : dpm docker stop run a service from the docker-compose file: docker-compose up -d <name_of_service> | example: docker-compose up -d mps-prod , docker-compose up -d app , ....","title":"Launch the application on local"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial-back.git","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#start-pilote-application","text":"To start Pilote application just launch the command in a Powershell or Windows Powershell tool: yarn docker:dev If the application starts successfully you should obtain two containers running: mps-travailleursocial-back_mps_1 mps-travailleursocial-back_postgres_1 You can access by: http://localhost:3020/api It will be redirect to the Swagger UI. It allow to test the different API defined.","title":"Start Pilote application"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#run-jest-test","text":"To start test defined just run the command in a Powershell or Windows Powershell tool: yarn test:watch Don't forget to uncomment ending row into beneficiary.service.ts file before to run the above command.","title":"Run Jest test"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#useful-docker-command","text":"build : docker build -t mps . run container : docker-compose -f docker-compose.yml up --remove-orphans access container db: docker exec -it mps-travailleursocial-back_postgres_1 psql -U postgres delete image/containers: docker system prune -a -f enter container: docker exec -it <id_container> bash remove container: docker container rm -f <id_container>","title":"Useful docker command"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/#synapps-environment","text":"check mps container : docker ps --filter \"name=mps\" or use this alias created : dpm docker stop run a service from the docker-compose file: docker-compose up -d <name_of_service> | example: docker-compose up -d mps-prod , docker-compose up -d app , ....","title":"Synapps environment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/","text":"This section will allow you to install a proper local environment step by step for Pilote application using VSCode IDE. VSCode Install VSCode Installation for VSCode can be found here: Installation of VSCode . Extensions Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension) User settings User settings for Ecolyo are described in this section: LINK TO SECTION TO ADD Git The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git . Node Version 12 For now please install node v12, any later version will cause side effects on sass modules! Download node-v12 Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Yarn Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn . Docker Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code. Install Docker Installation of Docker can be found here: Installation of Docker . Install Docker-Compose Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Setup your environment"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#vscode","text":"","title":"VSCode"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-vscode","text":"Installation for VSCode can be found here: Installation of VSCode .","title":"Install VSCode"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#extensions","text":"Installation of Extention is explained here: Installation of Extensions . Here are the list of important extensions to install: Prettier - Code formatter ES7 React/Redux/GraphQL/React-Native snippets GitLens - Git supercharged Markdown Preview Optional extensions: Bracket Pair Colorizer 2 CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension)","title":"Extensions"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#user-settings","text":"User settings for Ecolyo are described in this section: LINK TO SECTION TO ADD","title":"User settings"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#git","text":"The project is using GitLab, you will need to install Git to checkout the project. Installation for Git can be found here: Installation of Git .","title":"Git"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#node","text":"Version 12 For now please install node v12, any later version will cause side effects on sass modules! Download node-v12 Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine.","title":"Node"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#yarn","text":"Yarn is used as package manager for this project. Feel free to use the one you prefer but we advice to install yarn as all the documentation is described with this package manager. Installation for yarn can be found here: Installation of Yarn .","title":"Yarn"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#docker","text":"Docker is a tool designed to make it easier to create, deploy, and run applications by using containers. Containers allow a developer to package up an application with all of the parts it needs, such as libraries and other dependencies, and ship it all out as one package. By doing so, thanks to the container, the developer can rest assured that the application will run on any other Linux machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.","title":"Docker"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-docker","text":"Installation of Docker can be found here: Installation of Docker .","title":"Install Docker"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/getting_started/setup_your_environment/#install-docker-compose","text":"Installation of Docker-Compose (according to your OS) is explained here: Installation of Docker-Compose .","title":"Install Docker-Compose"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/","text":"Techno used NestJS Jest for the tests Docker PostgreSQL Docker-compose Two docker-compose are available into the project: - the general one - the local one For the general one, all service are details. The env variable used are available on Synapps server. The local one is used with the docker-compose_dev.yml","title":"Project Architecture"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/#techno-used","text":"NestJS Jest for the tests Docker PostgreSQL","title":"Techno used"},{"location":"pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/#docker-compose","text":"Two docker-compose are available into the project: - the general one - the local one For the general one, all service are details. The env variable used are available on Synapps server. The local one is used with the docker-compose_dev.yml","title":"Docker-compose"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/application/deploy/","text":"Deployment For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline liked is running.","title":"Deploy"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/application/deploy/#deployment","text":"For each environment, the CI-CD is implemented. Once, you commit on 'dev' branch or 'rec' branch, the pipeline liked is running.","title":"Deployment"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/","text":"This section explains the different functionalities: Beneficiaries Once you are authenticated, you'll redirect into /liste-beneficiaire route. You are getting all usager known. Sharing For each beneficiary, you can ask the sharing. It means that you will be redirect into the public page of the cozy usager. In the same time, one process is running in order to send the sms. This sms contain one sharecode in order to provide some right on the cozy usager. In order to help you to understand this process, you can check : Pilote - TS - Back/project_architecture/share_sms.png","title":"Routes"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/#beneficiaries","text":"Once you are authenticated, you'll redirect into /liste-beneficiaire route. You are getting all usager known.","title":"Beneficiaries"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/#sharing","text":"For each beneficiary, you can ask the sharing. It means that you will be redirect into the public page of the cozy usager. In the same time, one process is running in order to send the sms. This sms contain one sharecode in order to provide some right on the cozy usager. In order to help you to understand this process, you can check : Pilote - TS - Back/project_architecture/share_sms.png","title":"Sharing"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial.git Installation of the project Start Pilote application Before to start Pilote application, you need to run this command in order to install dependencies: yarn install To start Pilote application just launch the command in a Powershell or Windows Powershell tool: yarn start If the application starts successfully you should access to: http://localhost:3001/","title":"Launch the application on local"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#clone-the-project-repository","text":"Use following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-travailleursocial.git","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/#start-pilote-application","text":"Before to start Pilote application, you need to run this command in order to install dependencies: yarn install To start Pilote application just launch the command in a Powershell or Windows Powershell tool: yarn start If the application starts successfully you should access to: http://localhost:3001/","title":"Start Pilote application"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/","text":"Section under Construction This section will show you how to deploy your project on different environments. Setup First of all you'll need to install MobaXterm in order to connect to the server. Then, if you're on Linux you can skip the following section, otherwise if you are on Windows you'll have to install Windows Subsystem for Linux (WSL) since the deployment of the app is not working with windows commands. Install WSL First open Powershell as administrator and launch the following command : dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot . Install your Linux distribution After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 lts). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list. Setup your distribution Start Up Updating the packages list by typing : sudo apt update Install the nodejs using the apt package manager sudo apt install To verify the Installation execute the following command : nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type : sudo apt install npm To verify the npm Install check using the command : npm --version To Download and Setup Yarn sudo apt install yarn To check the Installed version of Yarn : yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands : sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on. Configuration of MobaXterm First open a new session and connect to the distant host 192.168.62.31 . Don't forget to add the path to the private key in the advanced SSH settings. Deploy Pilote Deploy on Alpha Windows First open your Ubuntu terminal, and clone the project in the repository of your choice. Once you've selected the branch of you want to deploy, write the following command : yarn build After this, you can launch the deployment. In order to deploy on pilote-dev-build (development environment) use the command : yarn deploy-dev If you want to deploy on the pilote-build environment, use : yarn deploy Linux From your current branch, run yarn build then sudo yarn deploy_dev to instantly deploy your working branch on the latest tagged Pilote container registry.","title":"Deploy"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#setup","text":"First of all you'll need to install MobaXterm in order to connect to the server. Then, if you're on Linux you can skip the following section, otherwise if you are on Windows you'll have to install Windows Subsystem for Linux (WSL) since the deployment of the app is not working with windows commands.","title":"Setup"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#install-wsl","text":"First open Powershell as administrator and launch the following command : dism . exe / online / enable-feature / featurename : Microsoft-Windows-Subsystem-Linux / all / norestart This command will install WSL on your computer. After this, you'll need to reboot .","title":"Install WSL"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#install-your-linux-distribution","text":"After reboot, open the microsoft store and install the distribution of your choice (for example : Ubuntu 20.04 lts). Once it's done, open it and after a few minutes you'll be prompted for the creation of a user account. To make sure it's correctly installed and working, you can open Powershell and paste the following command : wsl . exe - -list - -running Now you should see the name of your distribution in the list.","title":"Install your Linux distribution"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#setup-your-distribution","text":"Start Up Updating the packages list by typing : sudo apt update Install the nodejs using the apt package manager sudo apt install To verify the Installation execute the following command : nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type : sudo apt install npm To verify the npm Install check using the command : npm --version To Download and Setup Yarn sudo apt install yarn To check the Installed version of Yarn : yarn --version Now you'll probably be in version 0.23+git, if so you'll have to upgrade to 1.22 to make everything work properly. In order to achieve this, you'll have to launch several commands : sudo apt-get remove cmdtest sudo apt autoremove sudo apt-get update sudo apt install curl -y curl -o- -L https://yarnpkg.com/install.sh | bash source ~/.bashrc Now you should be at least in version ^1.22 and ready to go on.","title":"Setup your distribution"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#configuration-of-mobaxterm","text":"First open a new session and connect to the distant host 192.168.62.31 . Don't forget to add the path to the private key in the advanced SSH settings.","title":"Configuration of MobaXterm"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#deploy-pilote","text":"","title":"Deploy Pilote"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#deploy-on-alpha","text":"","title":"Deploy on Alpha"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#windows","text":"First open your Ubuntu terminal, and clone the project in the repository of your choice. Once you've selected the branch of you want to deploy, write the following command : yarn build After this, you can launch the deployment. In order to deploy on pilote-dev-build (development environment) use the command : yarn deploy-dev If you want to deploy on the pilote-build environment, use : yarn deploy","title":"Windows"},{"location":"pilote/Pilote%20-%20Usager/application/deploy/#linux","text":"From your current branch, run yarn build then sudo yarn deploy_dev to instantly deploy your working branch on the latest tagged Pilote container registry.","title":"Linux"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/","text":"Doctypes Doctypes represent different types of data. Their primary use is for permissions: an app or konnector will request permissions for one or several doctypes and will not be able to access other doctypes. See Doctypes documentation for more information. The following is a full description of the doctypes we use and their fields. Cozy doctypes won't be fully described. Instead, for every used one, we'll include a link to its official documentation. Used Cozy doctypes io.cozy.accounts : Konnector accounts io.cozy.apps : Installed apps io.cozy.contacts : Contacts io.cozy.contacts.groups : Contacts groups io.cozy.files : Files io.cozy.permissions : Permissions of the instance io.cozy.konnectors : Konnectors io.cozy.triggers : Job triggers Used Cozy remote doctypes This kind of doctype are set from the team. We have push two remote doctypes (each duplicate for rec and prod environment) Prod - [ org.mps.store ]: Required for store information on back-endTS - [ org.mps.share ]: Required for searching on back-endTS Recette [ org.mps.store.rec ]: Required for store information on rec back-endTS [ org.mps.share.rec ]: Required for searching on rec back-endTS If you need to target rec remote doctype, you need to change the request : client.getStackClient().fetchJSON('POST','...') and change them into the manifest also. Custom doctypes com.grandlyon.mps.profile ##### Attributes tutorial : { object } contains contacts , documents , actions , and notes . They represent the state of tutorials. For example, contacts: true means the contacts tutorial hasn't been seen yet and will be visible to the user the next time he visits the contacts component. notification : { boolean } If equals true, the user has a notification fullname : { string } User's full name introduction : { boolean } If equals true , it means the user has already used the app and seen the introduction. lastConnectionDate : { string } When was the user last connected (ISO string). hasPhone : { boolean } Equals true if the current user has already a phone number userID : { string } Current user id publicProfile : { object } contains fullname , endDate (ISO string), and isActive com.grandlyon.mps.appointments ##### Attributes id : { string } the appointment id appointmentDate : { string } the appointment date (ISO string) note : { Note } A unique note for each appointment objectives : { Array<Objective> } The list of appointment's objectives com.grandlyon.mps.objectives ##### Attributes id : { string } the objective id title : { string } the objective title type : { string } The id of the Objective type subtype : { string } The id of the Objective subType tasks : { Array<Task> } Array of Tasks ids archived : { boolean } If equals true, it mean the objective has been completed com.grandlyon.mps.tasks ##### Attributes id : { string } The task id name : { string } The task name description : { string } The task description state : { TaskState } It could be one of the following: 'USER_TO_VALID', 'USER_VALID', 'PUBLIC_VALID', 'PUBLIC_INVALID' qualifications : { Array<string> } items : { Array<TaskItem> } com.grandlyon.mps.task.items ##### Attributes id : { string } Item id file : { DocumentEntity } The items' file state : { TaskItemState } It could be one of the following: 'USER_ITEM_PENDING', 'PUBLIC_ITEM_VALID', 'PUBLIC_ITEM_INVALID' com.grandlyon.mps.notes ##### Attributes id : { string } Note's id content : { string } The content of the note. createdAt : { string } Date of creation (ISO string)","title":"Doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#doctypes","text":"Doctypes represent different types of data. Their primary use is for permissions: an app or konnector will request permissions for one or several doctypes and will not be able to access other doctypes. See Doctypes documentation for more information. The following is a full description of the doctypes we use and their fields. Cozy doctypes won't be fully described. Instead, for every used one, we'll include a link to its official documentation.","title":"Doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#used-cozy-doctypes","text":"io.cozy.accounts : Konnector accounts io.cozy.apps : Installed apps io.cozy.contacts : Contacts io.cozy.contacts.groups : Contacts groups io.cozy.files : Files io.cozy.permissions : Permissions of the instance io.cozy.konnectors : Konnectors io.cozy.triggers : Job triggers","title":"Used Cozy doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#used-cozy-remote-doctypes","text":"This kind of doctype are set from the team. We have push two remote doctypes (each duplicate for rec and prod environment) Prod - [ org.mps.store ]: Required for store information on back-endTS - [ org.mps.share ]: Required for searching on back-endTS Recette [ org.mps.store.rec ]: Required for store information on rec back-endTS [ org.mps.share.rec ]: Required for searching on rec back-endTS If you need to target rec remote doctype, you need to change the request : client.getStackClient().fetchJSON('POST','...') and change them into the manifest also.","title":"Used Cozy remote doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/doctypes/#custom-doctypes","text":"com.grandlyon.mps.profile ##### Attributes tutorial : { object } contains contacts , documents , actions , and notes . They represent the state of tutorials. For example, contacts: true means the contacts tutorial hasn't been seen yet and will be visible to the user the next time he visits the contacts component. notification : { boolean } If equals true, the user has a notification fullname : { string } User's full name introduction : { boolean } If equals true , it means the user has already used the app and seen the introduction. lastConnectionDate : { string } When was the user last connected (ISO string). hasPhone : { boolean } Equals true if the current user has already a phone number userID : { string } Current user id publicProfile : { object } contains fullname , endDate (ISO string), and isActive com.grandlyon.mps.appointments ##### Attributes id : { string } the appointment id appointmentDate : { string } the appointment date (ISO string) note : { Note } A unique note for each appointment objectives : { Array<Objective> } The list of appointment's objectives com.grandlyon.mps.objectives ##### Attributes id : { string } the objective id title : { string } the objective title type : { string } The id of the Objective type subtype : { string } The id of the Objective subType tasks : { Array<Task> } Array of Tasks ids archived : { boolean } If equals true, it mean the objective has been completed com.grandlyon.mps.tasks ##### Attributes id : { string } The task id name : { string } The task name description : { string } The task description state : { TaskState } It could be one of the following: 'USER_TO_VALID', 'USER_VALID', 'PUBLIC_VALID', 'PUBLIC_INVALID' qualifications : { Array<string> } items : { Array<TaskItem> } com.grandlyon.mps.task.items ##### Attributes id : { string } Item id file : { DocumentEntity } The items' file state : { TaskItemState } It could be one of the following: 'USER_ITEM_PENDING', 'PUBLIC_ITEM_VALID', 'PUBLIC_ITEM_INVALID' com.grandlyon.mps.notes ##### Attributes id : { string } Note's id content : { string } The content of the note. createdAt : { string } Date of creation (ISO string)","title":"Custom doctypes"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/","text":"Initialize Create a new project in GitLab and take note of its URL Protecting Master Branch On the GitLab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be merge requests. Setting Development Branch Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev Start Developing For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch Conventional Commits A feature branch name should follow this structure: feat/<title_of_the_user_story> You can create the branch by typing: git checkout -b feat/<title_of_the_user_story> Each fix branch should be named as the following fix-\\<title_of_the_fix> . Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Gitflow"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#initialize","text":"Create a new project in GitLab and take note of its URL","title":"Initialize"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#protecting-master-branch","text":"On the GitLab page of your project go to Settings/Repository in the Protected Branches section. Select the Master branch and set allow to merge to Master and allow to push to No one This will prevent anyone to push on the master branch, the only way to add code to the branch will be merge requests.","title":"Protecting Master Branch"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#setting-development-branch","text":"Retrieve the project on your computer, open a command line and execute. git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager.git Create the development branch git checkout -b dev Init your project and then type any time you want to commit changes: git add . git commit -m \"Commit changes\" git push origin dev","title":"Setting Development Branch"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#start-developing","text":"For any other development you should create a branch from the development branch. First make sure to be on the dev branch, type: git branch to see your current branch","title":"Start Developing"},{"location":"pilote/Pilote%20-%20Usager/application/gitflow/#conventional-commits","text":"A feature branch name should follow this structure: feat/<title_of_the_user_story> You can create the branch by typing: git checkout -b feat/<title_of_the_user_story> Each fix branch should be named as the following fix-\\<title_of_the_fix> . Breaking Change Appends a ! before the title of the commit to notify that a breaking change has happened. Give a solid description of the changes as well. add tag git tag -a 1.0.0 -m \"complementary message\"","title":"Conventional Commits"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/","text":"Scaffolding In this section, you will find information about the project file structure and the purpose of main folders and files. Source Files Folder/File Purpose assets The application's assets, contains fonts, SVGs, PNGs, and GIFs. doctypes Contains the cozy doctypes, you can see more on Cozy Documentation . helpers Contains helper functions that are used by services. It contains also a test file for each helper file. locales Contains JSON data used by the translation system i18n provided by Cozy-ui . models Contains all our models' Interfaces services Here you'll find all the services. It contains also a test file for each service file. store Redux store. Contains actions, reducers, and store types. styles Styles folder. The base folder under it contains our variables, fonts, breakpoints, animations, and mixins. Whenever you add a style file elsewhere, don't forget to import it in index.scss . targets Contains mobile and browser targets. It also contains a Public target for the service worker . types Contains all cozy types. utils In this folder you'll find utilities methods. components/App.tsx The root component. Configuration Files File Purpose .editorconfig Editor config rules .eslintrc.js ESLint config file gitlab-ci.yml Gitlab continuous integration config file .prettierrc Prettier extension config file app.config.* Overloads webpack configuration jest.config.js Jest config file manifest.webapp Manifest of the application, used by cozy for permissions' management. You can add permissions for doctypes here tsconfig.json TypeScript config file konnector-dev-config.json To locally test konnectors service-dev-config.json To locally test services","title":"Scaffolding"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#scaffolding","text":"In this section, you will find information about the project file structure and the purpose of main folders and files.","title":"Scaffolding"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#source-files","text":"Folder/File Purpose assets The application's assets, contains fonts, SVGs, PNGs, and GIFs. doctypes Contains the cozy doctypes, you can see more on Cozy Documentation . helpers Contains helper functions that are used by services. It contains also a test file for each helper file. locales Contains JSON data used by the translation system i18n provided by Cozy-ui . models Contains all our models' Interfaces services Here you'll find all the services. It contains also a test file for each service file. store Redux store. Contains actions, reducers, and store types. styles Styles folder. The base folder under it contains our variables, fonts, breakpoints, animations, and mixins. Whenever you add a style file elsewhere, don't forget to import it in index.scss . targets Contains mobile and browser targets. It also contains a Public target for the service worker . types Contains all cozy types. utils In this folder you'll find utilities methods. components/App.tsx The root component.","title":"Source Files"},{"location":"pilote/Pilote%20-%20Usager/application/scaffolding/#configuration-files","text":"File Purpose .editorconfig Editor config rules .eslintrc.js ESLint config file gitlab-ci.yml Gitlab continuous integration config file .prettierrc Prettier extension config file app.config.* Overloads webpack configuration jest.config.js Jest config file manifest.webapp Manifest of the application, used by cozy for permissions' management. You can add permissions for doctypes here tsconfig.json TypeScript config file konnector-dev-config.json To locally test konnectors service-dev-config.json To locally test services","title":"Configuration Files"},{"location":"pilote/Pilote%20-%20Usager/application/services/","text":"Profile Service Functions getProfile : Tries fetching the profile if it exists. If not, it creates a new one and returns it. updateProfile : Updates the profile. parseProfile : Returns the Profile passed as a parameter without the following properties: _id, id, _type, _rev, cozyMetadata . Notes Service Functions parseNote : Returns the Note passed as a parameter without the following properties: _id, _type, _rev, cozyMetadata . getNoteByIDs : Returns a list of Notes from a list of ids. createNote : Creates a new Note. updateNote : Updates a Note. getCurrentNoteOrCreate : Returns the Note linked to the current Appointment. If id does not exist, it creates and returns a new one. getAllNotes : Returns a list of all Notes. Appointments Service Functions parseAppointment : Returns an Appointment from an AppointmentEntity. getLastAppointment : Returns the last Appointment, which a user can see first in /actions. getAllAppointment : returns a list of all Appointments. getAppointmentByID : Returns an Appointment from its id. createAppointment : Creates a new Appointment. updateAppointment : Updates an Appointment. Documents Service Functions getAllDocuments : Returns the list of all documents. getDocumentsByQualification : Returns a document by a qualification. getDocumentsByQualifications : Uses getDocumentsByQualification to return a list of documents from a list of qualifications. getDocumentByID : Returns a document by its id. saveDocument : Creates a new file. editDocumentName : Edits a document's name by its id. deleteDocumentById : Deletes the document by its id. downloadDocument : Downloads a file from its id. downloadArchive : Downloads an archive containing all the files whom ids are passed as a parameter. getLinkDoc : Returns the file download link. getReferencedFolders : Gets a folder by a reference. getOrCreateFolderWithReference : Gets a folder by a reference or creates it if it does not exist. getDocumentsWithQualifications : Returns the qualified documents along with the not qualified ones ( { qualified, other } ). replaceFile : Replaces a file. keepFile : Changes a file's name and saves it. Contacts Service Functions getCurrentUser : Returns the contact with an existing me field, which represents the current user. getAllContacts : Returns a list of all contacts. findContactById : Returns a contact by its id. createContact : Creates a new contact. updateContact : Updates an existing contact. deleteContactById : Deletes a contact by its id. Groups Service Function createMetroGroup : Creates a new group and returns it. getMetroGroup : Returns the group if it exists or creates it if it doesn't. Initialization Service Initialization : { Object } Initializes the profile, actions, and the appDirectory. Konnectors Service Functions getAllKonnectors : Returns a list of all the Konnectors. getAllKonnectorSlugs : Returns a list of all the Konnectors' slugs. getKonnectorNameBySlug : Returns a Konnector name from a slug. getKonnectorBySlug : Returns a Konnector from a slug. getKonnectorByName : Returns a Konnector from its name. getKonnectorsFromDocuments : Returns a list of Konnectors from a passed DocumentEntity list. Objectives Service Functions parseObjective : Returns the Objective passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getObjectiveByIDs : Returns a list of Objectives from a list of ids. getOldObjectives : Returns a list of the archived Objectives not belonging to the last Appointment. createObjective : Creates a new Objective. updateObjective : Updates an existing Objective. Tasks Service Functions parseTaskJSONToTask : Returns a Task from a TaskJSON. parseTask : Returns the Task passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTasksByIDs : Returns a list of Tasks from a list of ids. createTask : Creates a new Task. updateTask : Updates a Task from its id. TaskItems Service Functions parseTaskItem : Returns the TaskItem passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTaskItemByIDs : Returns a list of TaskItems from a list of ids. createTaskItem : Creates a new TaskItem. updateTaskItem : Updates a TaskItem from its id. Triggers Service Functions getAllTriggers : Returns All the triggers filtered by type if passed as parameter.","title":"Services"},{"location":"pilote/Pilote%20-%20Usager/application/services/#profile-service","text":"","title":"Profile Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions","text":"getProfile : Tries fetching the profile if it exists. If not, it creates a new one and returns it. updateProfile : Updates the profile. parseProfile : Returns the Profile passed as a parameter without the following properties: _id, id, _type, _rev, cozyMetadata .","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#notes-service","text":"","title":"Notes Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_1","text":"parseNote : Returns the Note passed as a parameter without the following properties: _id, _type, _rev, cozyMetadata . getNoteByIDs : Returns a list of Notes from a list of ids. createNote : Creates a new Note. updateNote : Updates a Note. getCurrentNoteOrCreate : Returns the Note linked to the current Appointment. If id does not exist, it creates and returns a new one. getAllNotes : Returns a list of all Notes.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#appointments-service","text":"","title":"Appointments Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_2","text":"parseAppointment : Returns an Appointment from an AppointmentEntity. getLastAppointment : Returns the last Appointment, which a user can see first in /actions. getAllAppointment : returns a list of all Appointments. getAppointmentByID : Returns an Appointment from its id. createAppointment : Creates a new Appointment. updateAppointment : Updates an Appointment.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#documents-service","text":"","title":"Documents Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_3","text":"getAllDocuments : Returns the list of all documents. getDocumentsByQualification : Returns a document by a qualification. getDocumentsByQualifications : Uses getDocumentsByQualification to return a list of documents from a list of qualifications. getDocumentByID : Returns a document by its id. saveDocument : Creates a new file. editDocumentName : Edits a document's name by its id. deleteDocumentById : Deletes the document by its id. downloadDocument : Downloads a file from its id. downloadArchive : Downloads an archive containing all the files whom ids are passed as a parameter. getLinkDoc : Returns the file download link. getReferencedFolders : Gets a folder by a reference. getOrCreateFolderWithReference : Gets a folder by a reference or creates it if it does not exist. getDocumentsWithQualifications : Returns the qualified documents along with the not qualified ones ( { qualified, other } ). replaceFile : Replaces a file. keepFile : Changes a file's name and saves it.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#contacts-service","text":"","title":"Contacts Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_4","text":"getCurrentUser : Returns the contact with an existing me field, which represents the current user. getAllContacts : Returns a list of all contacts. findContactById : Returns a contact by its id. createContact : Creates a new contact. updateContact : Updates an existing contact. deleteContactById : Deletes a contact by its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#groups-service","text":"","title":"Groups Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#function","text":"createMetroGroup : Creates a new group and returns it. getMetroGroup : Returns the group if it exists or creates it if it doesn't.","title":"Function"},{"location":"pilote/Pilote%20-%20Usager/application/services/#initialization-service","text":"Initialization : { Object } Initializes the profile, actions, and the appDirectory.","title":"Initialization Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#konnectors-service","text":"","title":"Konnectors Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_5","text":"getAllKonnectors : Returns a list of all the Konnectors. getAllKonnectorSlugs : Returns a list of all the Konnectors' slugs. getKonnectorNameBySlug : Returns a Konnector name from a slug. getKonnectorBySlug : Returns a Konnector from a slug. getKonnectorByName : Returns a Konnector from its name. getKonnectorsFromDocuments : Returns a list of Konnectors from a passed DocumentEntity list.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#objectives-service","text":"","title":"Objectives Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_6","text":"parseObjective : Returns the Objective passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getObjectiveByIDs : Returns a list of Objectives from a list of ids. getOldObjectives : Returns a list of the archived Objectives not belonging to the last Appointment. createObjective : Creates a new Objective. updateObjective : Updates an existing Objective.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#tasks-service","text":"","title":"Tasks Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_7","text":"parseTaskJSONToTask : Returns a Task from a TaskJSON. parseTask : Returns the Task passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTasksByIDs : Returns a list of Tasks from a list of ids. createTask : Creates a new Task. updateTask : Updates a Task from its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#taskitems-service","text":"","title":"TaskItems Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_8","text":"parseTaskItem : Returns the TaskItem passed as a parameter without the following properties: _type, _rev, _id, cozyMetadata, relationships . getTaskItemByIDs : Returns a list of TaskItems from a list of ids. createTaskItem : Creates a new TaskItem. updateTaskItem : Updates a TaskItem from its id.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/services/#triggers-service","text":"","title":"Triggers Service"},{"location":"pilote/Pilote%20-%20Usager/application/services/#functions_9","text":"getAllTriggers : Returns All the triggers filtered by type if passed as parameter.","title":"Functions"},{"location":"pilote/Pilote%20-%20Usager/application/store/","text":"Redux We are using Redux for our application state management. it maintains the state of the entire application in a single immutable state tree (object), which can't be changed directly. When something changes, a new object is created (using actions and reducers). For more information about Redux, visit The [official documentation][https://redux.js.org/]. Store The following are the existing store entities used by our application: Profile : Preserves the state of tutorials, user profile, public profile, introduction, and notifications (see initial state below). Global : Preserves the global state, which includes isPublic toast and error Appointment : Preserves the state of tutorials and notifications. UploadDocument : Manages the state of uploaded documents. Initial states Profile { tutorial : { // Tells if a tutorial has already been seen contacts : true , documents : true , actions : { first : true , // 'first' represents the actions component with no appointments yet second : true , // 'second' represents the actions component with an existing appointment }, }, fullname : '' , introduction : true , // If 'true', the user has already used the app and seen the introduction notification : false , lastConnectionDate : '' , // ISO string hasPhone : false , userID : '' , publicProfile : { fullname : '' , endDate : '' , // Timestamp isActive : false , }, } Global { isPublic : false , toast : null , // Manages global messages toasts error : false , // Manages global errors } Appointment { id : '' , appointmentDate : '' , // ISO string note : { id : '' , content : '' , createdAt : '' , // ISO string }, objectives : [], } UploadDocument { file : null , qualification : null , } For each reducer file, a test file is associated testing the reducer. All the actions are tested in a separate file with the same actions file name. Used packages react-redux : Official React bindings for Redux . react-redux : Thunk middleware for Redux. redux-devtools-extension : For application's state changes debugging. @types/react-redux : This package contains type definitions for react-redux.","title":"Store"},{"location":"pilote/Pilote%20-%20Usager/application/store/#redux","text":"We are using Redux for our application state management. it maintains the state of the entire application in a single immutable state tree (object), which can't be changed directly. When something changes, a new object is created (using actions and reducers). For more information about Redux, visit The [official documentation][https://redux.js.org/].","title":"Redux"},{"location":"pilote/Pilote%20-%20Usager/application/store/#store","text":"The following are the existing store entities used by our application: Profile : Preserves the state of tutorials, user profile, public profile, introduction, and notifications (see initial state below). Global : Preserves the global state, which includes isPublic toast and error Appointment : Preserves the state of tutorials and notifications. UploadDocument : Manages the state of uploaded documents.","title":"Store"},{"location":"pilote/Pilote%20-%20Usager/application/store/#initial-states","text":"","title":"Initial states"},{"location":"pilote/Pilote%20-%20Usager/application/store/#profile","text":"{ tutorial : { // Tells if a tutorial has already been seen contacts : true , documents : true , actions : { first : true , // 'first' represents the actions component with no appointments yet second : true , // 'second' represents the actions component with an existing appointment }, }, fullname : '' , introduction : true , // If 'true', the user has already used the app and seen the introduction notification : false , lastConnectionDate : '' , // ISO string hasPhone : false , userID : '' , publicProfile : { fullname : '' , endDate : '' , // Timestamp isActive : false , }, }","title":"Profile"},{"location":"pilote/Pilote%20-%20Usager/application/store/#global","text":"{ isPublic : false , toast : null , // Manages global messages toasts error : false , // Manages global errors }","title":"Global"},{"location":"pilote/Pilote%20-%20Usager/application/store/#appointment","text":"{ id : '' , appointmentDate : '' , // ISO string note : { id : '' , content : '' , createdAt : '' , // ISO string }, objectives : [], }","title":"Appointment"},{"location":"pilote/Pilote%20-%20Usager/application/store/#uploaddocument","text":"{ file : null , qualification : null , } For each reducer file, a test file is associated testing the reducer. All the actions are tested in a separate file with the same actions file name.","title":"UploadDocument"},{"location":"pilote/Pilote%20-%20Usager/application/store/#used-packages","text":"react-redux : Official React bindings for Redux . react-redux : Thunk middleware for Redux. redux-devtools-extension : For application's state changes debugging. @types/react-redux : This package contains type definitions for react-redux.","title":"Used packages"},{"location":"pilote/Pilote%20-%20Usager/functionalities/appointments/","text":"This section explain all the functionalities in the appointment part","title":"Appointments"},{"location":"pilote/Pilote%20-%20Usager/functionalities/contact/","text":"Description Pilote allow usager to add contact : - You will always see your profil at the first contact. You can not delete it. Just edit it. - Then, with the add concat button, you can add others contact","title":"Contact"},{"location":"pilote/Pilote%20-%20Usager/functionalities/contact/#description","text":"Pilote allow usager to add contact : - You will always see your profil at the first contact. You can not delete it. Just edit it. - Then, with the add concat button, you can add others contact","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/","text":"Description Pilote Usager is linked to a registry to allow a TS to find and connect to a user Pilote app. A service is run every day to send instance information to the registry. Service Flow summarized Launch the service locally Switch to Node 16 (using nvm or n) install local remote doctypes (details here ), add a folder named org.mps.registry.dev, inside it add a file named request with the following content : POST https://cozy-registry.poc.self-data.alpha.grandlyon.com/api/pilote Authorization: Bearer {{secret_token}} Content-Type: application/json {{data}} in the database, if it doesn't exist, create a table named secrets/io-cozy-remote-secrets and add a document with the following content : { \"_id\" : \"org.mps.registry.dev\" , \"token\" : \"pilotecozytoken\" } launch docker-compose up in a first terminal launch yarn build in a second terminal launch yarn run cozy-konnector-dev -m ./manifest.webapp ./build/services/cozyRegistry/pilote.js to execute the service","title":"Cozy Registry"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#description","text":"Pilote Usager is linked to a registry to allow a TS to find and connect to a user Pilote app. A service is run every day to send instance information to the registry.","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#service-flow-summarized","text":"","title":"Service Flow summarized"},{"location":"pilote/Pilote%20-%20Usager/functionalities/cozy-registry/#launch-the-service-locally","text":"Switch to Node 16 (using nvm or n) install local remote doctypes (details here ), add a folder named org.mps.registry.dev, inside it add a file named request with the following content : POST https://cozy-registry.poc.self-data.alpha.grandlyon.com/api/pilote Authorization: Bearer {{secret_token}} Content-Type: application/json {{data}} in the database, if it doesn't exist, create a table named secrets/io-cozy-remote-secrets and add a document with the following content : { \"_id\" : \"org.mps.registry.dev\" , \"token\" : \"pilotecozytoken\" } launch docker-compose up in a first terminal launch yarn build in a second terminal launch yarn run cozy-konnector-dev -m ./manifest.webapp ./build/services/cozyRegistry/pilote.js to execute the service","title":"Launch the service locally"},{"location":"pilote/Pilote%20-%20Usager/functionalities/document/","text":"This section explains how to handle data storage.","title":"Document"},{"location":"pilote/Pilote%20-%20Usager/functionalities/setting/","text":"Description Pilote has setting page. You can found : - Notifications: Under construction - Tutorial: allow to view again one of the tutorial available - FAQ: Different explication of the global application - Legal Notice","title":"Settings"},{"location":"pilote/Pilote%20-%20Usager/functionalities/setting/#description","text":"Pilote has setting page. You can found : - Notifications: Under construction - Tutorial: allow to view again one of the tutorial available - FAQ: Different explication of the global application - Legal Notice","title":"Description"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/","text":"Initialisation of the project Clone the project repository Use the following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager Installation of the project Start Pilote Usager application Before starting Pilote Usager application, you need to install dependencies: yarn install To start Pilote Usager application, you first need start the application and start a cozy stack: yarn start docker-compose up As the pilote application has been recently upgraded to NodeJS 16 version, you might need to install additionnal packages in order to be able to run the app. Make sure your have the following installed : Python3 Microsoft Visual Studio tools 2017 node-gyp And wait for the success message. Everything is setup. Go to http://pilote.cozy.tools:8080/ Once successful you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '. Start Pilote TS application To start a social worker instance, go to options page and click ' Get sharecode '. Open the console and you'll see a link redirecting to a TS instance.","title":"Launch local application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#initialisation-of-the-project","text":"","title":"Initialisation of the project"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#clone-the-project-repository","text":"Use the following command in your favorite terminal to clone the project: git clone https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager","title":"Clone the project repository"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#installation-of-the-project","text":"","title":"Installation of the project"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#start-pilote-usager-application","text":"Before starting Pilote Usager application, you need to install dependencies: yarn install To start Pilote Usager application, you first need start the application and start a cozy stack: yarn start docker-compose up As the pilote application has been recently upgraded to NodeJS 16 version, you might need to install additionnal packages in order to be able to run the app. Make sure your have the following installed : Python3 Microsoft Visual Studio tools 2017 node-gyp And wait for the success message. Everything is setup. Go to http://pilote.cozy.tools:8080/ Once successful you can launch your local cozy with following url Cozy local url and connect with the password ' cozy '.","title":"Start Pilote Usager application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_application/#start-pilote-ts-application","text":"To start a social worker instance, go to options page and click ' Get sharecode '. Open the console and you'll see a link redirecting to a TS instance.","title":"Start Pilote TS application"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/","text":"Use cozy-doctype in local In order to be able to use our own cozy-doctype, especially remote doctype here, we need to use them in local. 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes warning You need to build and push the newest image on the forge registry when the step 3 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! For this project: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 4/ The path \"/data/cozy-doctypes\" is linked to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes How to test your remote doctype ? GET 1/ In the request file created. Specify the method and the route to your target URL : GET https://pilote-agent-dev.grandlyon.com/api/cozy or with value in query : GET https://pilote-agent-dev.grandlyon.com/api/auth/token/check?token={{token}} 2/ Then, you can test it by : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share') or with value in query : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2OTI0NjYsImV4cCI6MTYwNTY5MjUyNn0.HbQh5H-TcVIASUpbjZAD0MY9slRAJOVw-VMKSBu_sQ0' ) POST 1/ In the request file created. Specify the methode and the route to your target URL : POST https://pilote-agent-dev.grandlyon.com/api/auth/token/check Content-Type: application/json {{data}} 2/ Then, you can test it by : const parameters = { data: JSON.stringify({ token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2MjYxNzAsImV4cCI6MTYwNTYyNjIzMH0.8m-rEAZkuqb4upAPKY7j8DhvFi8mVbmiCFDitgNYt6Y\" } ) } console.log('call remote ==> ', await client.getStackClient().fetchJSON('POST','/remote/org.mps.share', parameters ))","title":"Launch local doctypes"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#use-cozy-doctype-in-local","text":"In order to be able to use our own cozy-doctype, especially remote doctype here, we need to use them in local. 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes warning You need to build and push the newest image on the forge registry when the step 3 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! For this project: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 4/ The path \"/data/cozy-doctypes\" is linked to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes","title":"Use cozy-doctype in local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#how-to-test-your-remote-doctype","text":"","title":"How to test your remote doctype ?"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#get","text":"1/ In the request file created. Specify the method and the route to your target URL : GET https://pilote-agent-dev.grandlyon.com/api/cozy or with value in query : GET https://pilote-agent-dev.grandlyon.com/api/auth/token/check?token={{token}} 2/ Then, you can test it by : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share') or with value in query : await client.getStackClient().fetchJSON('GET','/remote/org.mps.share?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2OTI0NjYsImV4cCI6MTYwNTY5MjUyNn0.HbQh5H-TcVIASUpbjZAD0MY9slRAJOVw-VMKSBu_sQ0' )","title":"GET"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/#post","text":"1/ In the request file created. Specify the methode and the route to your target URL : POST https://pilote-agent-dev.grandlyon.com/api/auth/token/check Content-Type: application/json {{data}} 2/ Then, you can test it by : const parameters = { data: JSON.stringify({ token: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNvenlBcGlDaGVjayIsInVzZXJJZCI6IjEiLCJpYXQiOjE2MDU2MjYxNzAsImV4cCI6MTYwNTYyNjIzMH0.8m-rEAZkuqb4upAPKY7j8DhvFi8mVbmiCFDitgNYt6Y\" } ) } console.log('call remote ==> ', await client.getStackClient().fetchJSON('POST','/remote/org.mps.share', parameters ))","title":"POST"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/","text":"Use services in local Configure the cozy-stack on local In order to be able to use your sercice, follow these steps: 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes 4/ You need to add another option when you install apps in the cozy-stack (go to: docker\\cozy-app-dev-with-app.sh) In do_install_app(): #add symbolic link to mps for sms service ln -s /data/cozy-app/mps /data/cozy-storage/cozy.tools\\:8080/.cozy_apps/mps if [ -d \"data/cozy-app/mps/0.1.1\" ]; then echo \"data/cozy-app/mps/0.1.1 already here!\"; else mkdir /data/cozy-app/mps/0.1.1 cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"data/cozy-app/mps/0.1.1 just create!\"; fi # mkdir /data/cozy-app/mps/0.1.1 # cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"service added\" 5/ Then, add konnector-node-run.sh in docker folder. This file is a script to store the service logs. It should contain: #!/bin/bash rundir=\"${1}\" cd $rundir node index.js | tee /data/cozy-app/mps/services.log Then, add this following row into the Dockerfile: COPY konnector-node-run.sh /etc/cozy/konnector-node-run.sh 6/ Into the disableCSP.yml, you need to add one more configuration: konnectors: cmd: /etc/cozy/konnector-node-run.sh # run connectors with node warning You need to build and push the newest image on the forge registry when the step 6 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! Finally, you should rebuild the docker image of the cozy-stack: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 7/ The path \"/data/cozy-doctypes\" is link to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes How to test your service ? In the manifest.webapp, you need to declare the service: \"services\": { \"smsProcess\": { \"type\": \"node\", \"file\": \"services/smsProcess/pilote.js\" } }, Then, in src\\targets\\services, you can add your service. For this project, we have created a button in Home.component.tsx in order to generate trigger url to run the service: const getTrigger = async () => { const attrs = { type: '@webhook', worker: 'service', message: { name: 'smsProcess', slug: 'pilotedemo', }, } const trigger = await client.getStackClient() .collection('io.cozy.triggers') .create(attrs) console.log('trigger', trigger) } It generates an trigger URL that we can call with our backend application : URL_COZY/job/webhook/{{trigger_id}} URL_COZY represent the cozy-stack url of your environment and not your application URL.","title":"Launch local services"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#use-services-in-local","text":"","title":"Use services in local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#configure-the-cozy-stack-on-local","text":"In order to be able to use your sercice, follow these steps: 1/ clone cozy-doctypes repository into your system. Then, push it into your root project. 2/ After that, add your own remote doctype into cozy-doctype folder: create a new folder ex: org.mps.share push into this folder request file: request You must declare this doctype into your manifest.webapp file like that : \"share\": { \"description\": \"Required for searching on back-endTS\", \"type\": \"org.mps.share\", \"verbs\": [\"GET\", \"POST\"] }, 3/ In cozy-app-dev-with-app.sh, you need to add another option when you serve the cozy-stack: cozy-stack serve --allow-root (...) --doctypes /path/to/the/doctype => in this project : cozy-stack serve (...) --doctypes /data/cozy-doctypes 4/ You need to add another option when you install apps in the cozy-stack (go to: docker\\cozy-app-dev-with-app.sh) In do_install_app(): #add symbolic link to mps for sms service ln -s /data/cozy-app/mps /data/cozy-storage/cozy.tools\\:8080/.cozy_apps/mps if [ -d \"data/cozy-app/mps/0.1.1\" ]; then echo \"data/cozy-app/mps/0.1.1 already here!\"; else mkdir /data/cozy-app/mps/0.1.1 cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"data/cozy-app/mps/0.1.1 just create!\"; fi # mkdir /data/cozy-app/mps/0.1.1 # cp -a /data/cozy-app/mps/services/ /data/cozy-app/mps/0.1.1/ echo \"service added\" 5/ Then, add konnector-node-run.sh in docker folder. This file is a script to store the service logs. It should contain: #!/bin/bash rundir=\"${1}\" cd $rundir node index.js | tee /data/cozy-app/mps/services.log Then, add this following row into the Dockerfile: COPY konnector-node-run.sh /etc/cozy/konnector-node-run.sh 6/ Into the disableCSP.yml, you need to add one more configuration: konnectors: cmd: /etc/cozy/konnector-node-run.sh # run connectors with node warning You need to build and push the newest image on the forge registry when the step 6 is done. You must have all files, into your docker folder, in LF mode of \"End of Line Sequence\" ! Finally, you should rebuild the docker image of the cozy-stack: cd docker docker build . docker tag <image_ID_created> registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes docker push registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes:latest 7/ The path \"/data/cozy-doctypes\" is link to the volume of the cozy-app-dev image. In order to mount this volume, you need to add it when you run the 'docker run' command : -v $PWD/cozy-doctypes:/data/cozy-doctypes => for this project : docker run --rm -it -p 8080:8080 -p 5984:5984 -p 8025:8025 -v $PWD/build:/data/cozy-app/mps -v $PWD/data:/usr/local/couchdb/data -v $PWD/docker/disableCSP.yaml:/etc/cozy/cozy.yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes registry.forge.grandlyon.com/solidarite/monparcourssocial/mps-usager/cozy-env-doctypes","title":"Configure the cozy-stack on local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#how-to-test-your-service","text":"In the manifest.webapp, you need to declare the service: \"services\": { \"smsProcess\": { \"type\": \"node\", \"file\": \"services/smsProcess/pilote.js\" } }, Then, in src\\targets\\services, you can add your service. For this project, we have created a button in Home.component.tsx in order to generate trigger url to run the service: const getTrigger = async () => { const attrs = { type: '@webhook', worker: 'service', message: { name: 'smsProcess', slug: 'pilotedemo', }, } const trigger = await client.getStackClient() .collection('io.cozy.triggers') .create(attrs) console.log('trigger', trigger) } It generates an trigger URL that we can call with our backend application : URL_COZY/job/webhook/{{trigger_id}} URL_COZY represent the cozy-stack url of your environment and not your application URL.","title":"How to test your service ?"},{"location":"proxy/description/","text":"This section of documentation refers to the Oauth protocols working hand in hand with our custom proxy and the cozy-stack. To fully understand its whereabouts, you should also look at the enedis konnector and grdf konnector documentation. proxy code source Feel free to check the proxy code at all time when reading this documentation. Oauth Dance To access customer data, one must first obtain customer authorization. This authorization is materialized by an access token and it must be obtained by the APIs exposed by each energy providers. These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent. See both Enedis and Grdf use cases before going further. Cozy Oauth Protocol cozy oauth flow documentation https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow Couchdb The couchdb database must hold all information needed for the konnector authentication to work properly. Auth information are stored in the secrets/io-cozy-account_types database. You can create manually the document by entering these parameters for each konnector: Name Description _id Name of your konnector, for instance: enedisgrandlyon grant_mode authorization_code client_id Application id given by the API provider client_secret Secret also given by the API provider auth_endpoint Authorize endpoint to request when starting the oauth protocol token_endpoint Token endpoint to request, will be called when the auth endpoint response reaches the stack token_mode get Once the document is created, when launching the konnector from the cozy-home or inside the running application. The oauth flow will start. The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step. If the token request is a success. An account/service-name database will be added in couchdb containing all information needed for authentication and the konnector will be free to work on all endpoints within its scope. Why we Need a Proxy The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personal clouds, following this guideline would mean that we need a client_id and a client_secret for each one of all the applications running. To answer this issue, two solutions are possible depending on what the energy supplier is willing to do. Providers could allow wildcard subdomains when registering the callback URI, it would parse the subdomain and adapt its redirection when answering /auth call. Example: https//*.cozygrandlyon.cloud/account/redirect -> parse subdomain before .cozy xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz toto.cozygrandlyon.cloud/account/redirect -> redirect to toto If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirection. Result With that in mind, the proxy is now the one calling the auth and token provider endpoints. The instance name will be contained in redirect_uri, the stack will insert this parameters by itself in the /auth call. 3 endpoints are created in the proxy for each energy supplier : One for the auth One for the token One for the redirect uri Proxy flow Proxy Code Explained reminder Feel free to check the proxy code at all time when reading this documentation. The proxy is coded in golang. It is composed of six endpoints as seen above. The first endpoint to be called is /auth . auth Originally called from a cozy-stack trying to setup its konnector. The proxy gets these information from the query: client_id duration redirect_uri (auto inserted by the cozy-stack, except if you specify skip_redirect_uri:true in the couchdb) response_type state (as it was conceived by the cozy-stack) The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling. With all these information, the proxy can contact the provider /auth endpoint to start the oauth dance. Enedis note See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the original instance name. This will be useful when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer. Once the call is sent, enedis will point to the /redirect endpoint. Grdf To be redacted redirect Retrieve the code , usage_point_id , and state answered by Enedis. Split the customed state that was modified in the /auth process. From this split it creates two variables : state host Finally redirect all these parameters in a query to the cozy-stack (the cozy-stack which is still waiting for an answer from its /auth call). state / instance The state must be recovered without the instance name, otherwise the cozy-stack won't recognized it and the handshake will fail. token Gathering from query or parameters all params. Sends a post request to the provider /token endpoint. The stack will store the response params in a accounts couchdb database.","title":"Description"},{"location":"proxy/description/#oauth-dance","text":"To access customer data, one must first obtain customer authorization. This authorization is materialized by an access token and it must be obtained by the APIs exposed by each energy providers. These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent. See both Enedis and Grdf use cases before going further.","title":"Oauth Dance"},{"location":"proxy/description/#cozy-oauth-protocol","text":"cozy oauth flow documentation https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow","title":"Cozy Oauth Protocol"},{"location":"proxy/description/#couchdb","text":"The couchdb database must hold all information needed for the konnector authentication to work properly. Auth information are stored in the secrets/io-cozy-account_types database. You can create manually the document by entering these parameters for each konnector: Name Description _id Name of your konnector, for instance: enedisgrandlyon grant_mode authorization_code client_id Application id given by the API provider client_secret Secret also given by the API provider auth_endpoint Authorize endpoint to request when starting the oauth protocol token_endpoint Token endpoint to request, will be called when the auth endpoint response reaches the stack token_mode get Once the document is created, when launching the konnector from the cozy-home or inside the running application. The oauth flow will start. The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step. If the token request is a success. An account/service-name database will be added in couchdb containing all information needed for authentication and the konnector will be free to work on all endpoints within its scope.","title":"Couchdb"},{"location":"proxy/description/#why-we-need-a-proxy","text":"The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personal clouds, following this guideline would mean that we need a client_id and a client_secret for each one of all the applications running. To answer this issue, two solutions are possible depending on what the energy supplier is willing to do. Providers could allow wildcard subdomains when registering the callback URI, it would parse the subdomain and adapt its redirection when answering /auth call. Example: https//*.cozygrandlyon.cloud/account/redirect -> parse subdomain before .cozy xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz toto.cozygrandlyon.cloud/account/redirect -> redirect to toto If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirection.","title":"Why we Need a Proxy"},{"location":"proxy/description/#result","text":"With that in mind, the proxy is now the one calling the auth and token provider endpoints. The instance name will be contained in redirect_uri, the stack will insert this parameters by itself in the /auth call. 3 endpoints are created in the proxy for each energy supplier : One for the auth One for the token One for the redirect uri","title":"Result"},{"location":"proxy/description/#proxy-flow","text":"","title":"Proxy flow"},{"location":"proxy/description/#proxy-code-explained","text":"reminder Feel free to check the proxy code at all time when reading this documentation. The proxy is coded in golang. It is composed of six endpoints as seen above. The first endpoint to be called is /auth .","title":"Proxy Code Explained"},{"location":"proxy/description/#auth","text":"Originally called from a cozy-stack trying to setup its konnector. The proxy gets these information from the query: client_id duration redirect_uri (auto inserted by the cozy-stack, except if you specify skip_redirect_uri:true in the couchdb) response_type state (as it was conceived by the cozy-stack) The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling. With all these information, the proxy can contact the provider /auth endpoint to start the oauth dance.","title":"auth"},{"location":"proxy/description/#enedis","text":"note See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the original instance name. This will be useful when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer. Once the call is sent, enedis will point to the /redirect endpoint.","title":"Enedis"},{"location":"proxy/description/#grdf","text":"To be redacted","title":"Grdf"},{"location":"proxy/description/#redirect","text":"Retrieve the code , usage_point_id , and state answered by Enedis. Split the customed state that was modified in the /auth process. From this split it creates two variables : state host Finally redirect all these parameters in a query to the cozy-stack (the cozy-stack which is still waiting for an answer from its /auth call). state / instance The state must be recovered without the instance name, otherwise the cozy-stack won't recognized it and the handshake will fail.","title":"redirect"},{"location":"proxy/description/#token","text":"Gathering from query or parameters all params. Sends a post request to the provider /token endpoint. The stack will store the response params in a accounts couchdb database.","title":"token"},{"location":"proxy/monitoring/","text":"All logs printed by the Proxy are read and translated into statistics on a grafana dashboard. Grafana scaleway monitoring production address This monitoring system allow the team to parse more easily the cozy-stack logs when something goes wrong. For instance, test konnector or check from the proxy if an issue was coming from Enedis or Grdf. Learn more about how it works here . High volume The service parses a very high amount of logs, most of all when debugging an instance. To limit our disk usage we tend to stop the service when not needed. Just type docker-compose down to stop it in monitoring/logs-monitoring. The docker volume will be persisted. To easily plug loki on a specific instance: Click on configuration and data sources Add data sources Find Loki and type the loki url http://loki:3100 In the query builder select the container \"easy-cozy\" then add |= \"domain=[specific-instance]\"","title":"Monitoring"},{"location":"proxy/use_cases/enedis/","text":"Enedis Data Connect enedis documentation Create an account on https://datahub-enedis.fr/ to explore all the services exposed by Enedis. Authorize API swagger. Api healthcheck . Regarding Enedis, two endpoints are exposed: Authorize /dataconnect/v1/oauth2/authorize Parameter Description client_id Unique identifier of the Application response_type Authorization scenario requested. It will always be \"code\" as Enedis implemented a code grant authorization state Security parameter allowing to maintain the state between the request and the redirection. ** Maximum length of 100 characters ! ** duration Duration of the consent requested by the application, ISO 8601 format. It cannot exceed 3 years Important The response targets the redirect-uri registered with Enedis (the redirect-uri is our proxy and the response will be explained in details further below when explaining the proxy endpoints mechanics). Token /v1/oauth2/token Parameter Description redirect_uri URI defined when the application was created. Must be secured in https content-type application/json grant_type Authorization type to get an access token. This must be set to \u201cauthorization_code\u201d when using an authorization code, and to \u201crefresh_token\u201d when using a refresh token client_id Unique identifier of the Application client_secret Secret of the client application, associated with its client_id refresh_token Refresh token returned to the previous POST request to the /token endpoint code Authorization code returned to the GET request of /authorize endpoint On success, response will contain access_token or refresh_token , usage_point_id among other things. All information will be stored by the cozy-stack in a cozy-accounts database. Consent Handling Consent is replaced every time a new oauth dance is launched (for 6 months, hard coded in /authorize request). User can revoke its consent from the Enedis website, no external endpoints are available for this purpose. If a consent has been revoked or expired. A 403 error will be thrown saying: No consent can be found for this customer and this usage point . Ecolyo can warn the user that the service is unable to continue and ask to give new consent.","title":"Enedis"},{"location":"proxy/use_cases/enedis/#enedis-data-connect","text":"enedis documentation Create an account on https://datahub-enedis.fr/ to explore all the services exposed by Enedis. Authorize API swagger. Api healthcheck . Regarding Enedis, two endpoints are exposed:","title":"Enedis Data Connect"},{"location":"proxy/use_cases/enedis/#authorize","text":"","title":"Authorize"},{"location":"proxy/use_cases/enedis/#dataconnectv1oauth2authorize","text":"Parameter Description client_id Unique identifier of the Application response_type Authorization scenario requested. It will always be \"code\" as Enedis implemented a code grant authorization state Security parameter allowing to maintain the state between the request and the redirection. ** Maximum length of 100 characters ! ** duration Duration of the consent requested by the application, ISO 8601 format. It cannot exceed 3 years Important The response targets the redirect-uri registered with Enedis (the redirect-uri is our proxy and the response will be explained in details further below when explaining the proxy endpoints mechanics).","title":"/dataconnect/v1/oauth2/authorize"},{"location":"proxy/use_cases/enedis/#token","text":"","title":"Token"},{"location":"proxy/use_cases/enedis/#v1oauth2token","text":"Parameter Description redirect_uri URI defined when the application was created. Must be secured in https content-type application/json grant_type Authorization type to get an access token. This must be set to \u201cauthorization_code\u201d when using an authorization code, and to \u201crefresh_token\u201d when using a refresh token client_id Unique identifier of the Application client_secret Secret of the client application, associated with its client_id refresh_token Refresh token returned to the previous POST request to the /token endpoint code Authorization code returned to the GET request of /authorize endpoint On success, response will contain access_token or refresh_token , usage_point_id among other things. All information will be stored by the cozy-stack in a cozy-accounts database.","title":"/v1/oauth2/token"},{"location":"proxy/use_cases/enedis/#consent-handling","text":"Consent is replaced every time a new oauth dance is launched (for 6 months, hard coded in /authorize request). User can revoke its consent from the Enedis website, no external endpoints are available for this purpose. If a consent has been revoked or expired. A 403 error will be thrown saying: No consent can be found for this customer and this usage point . Ecolyo can warn the user that the service is unable to continue and ask to give new consent.","title":"Consent Handling"},{"location":"proxy/use_cases/grdfadict/","text":"Grdf Adict grdf documentation Visit https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict to explore all the services exposed by Grdf. Prod endpoints are: https://sofit-sso-oidc.grdf.fr/openam/ Regarding Grdf Adict Oauth connection, two endpoints are exposed: Oauth connection still in Beta Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a state parameter in the Oauth dance. Authorize /oauth2/realms/externeGrdf/authorize Token /oauth2/realms/externeGrdf/access_token The /access_token endpoint can be called with two different grant_type parameter. authorization_code gives an access token and will also retrieve the consents list given by the user in session. client_credentials gives only the access token allowing us to request the data service. The grdf Konnector would only need to call the client_credentials to get a refresh token. Consent Handling Consent is represented by an access right. This access holds characteristics specific to the consent of the end customer. Optional: Revoke consent from external applications It is possible to cancel a consent that was given from the user to our service (for test or development purpose for instance). api.grdf.fr/adict/v1/droit_acces/{id_accreditation}","title":"Grdf Adict"},{"location":"proxy/use_cases/grdfadict/#grdf-adict","text":"grdf documentation Visit https://sites.grdf.fr/web/portail-api-grdf-adict/documentation-grdf-adict to explore all the services exposed by Grdf. Prod endpoints are: https://sofit-sso-oidc.grdf.fr/openam/ Regarding Grdf Adict Oauth connection, two endpoints are exposed: Oauth connection still in Beta Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a state parameter in the Oauth dance.","title":"Grdf Adict"},{"location":"proxy/use_cases/grdfadict/#authorize","text":"","title":"Authorize"},{"location":"proxy/use_cases/grdfadict/#oauth2realmsexternegrdfauthorize","text":"","title":"/oauth2/realms/externeGrdf/authorize"},{"location":"proxy/use_cases/grdfadict/#token","text":"","title":"Token"},{"location":"proxy/use_cases/grdfadict/#oauth2realmsexternegrdfaccess_token","text":"The /access_token endpoint can be called with two different grant_type parameter. authorization_code gives an access token and will also retrieve the consents list given by the user in session. client_credentials gives only the access token allowing us to request the data service. The grdf Konnector would only need to call the client_credentials to get a refresh token.","title":"/oauth2/realms/externeGrdf/access_token"},{"location":"proxy/use_cases/grdfadict/#consent-handling","text":"Consent is represented by an access right. This access holds characteristics specific to the consent of the end customer.","title":"Consent Handling"},{"location":"proxy/use_cases/grdfadict/#optional-revoke-consent-from-external-applications","text":"It is possible to cancel a consent that was given from the user to our service (for test or development purpose for instance). api.grdf.fr/adict/v1/droit_acces/{id_accreditation}","title":"Optional: Revoke consent from external applications"}]}
\ No newline at end of file
diff --git a/site/sitemap.xml b/site/sitemap.xml
index f35001b19df632b0de15f3458a3cb8326838347c..43c295d4439111c4ea50c732b31d3638b2b4c55f 100644
--- a/site/sitemap.xml
+++ b/site/sitemap.xml
@@ -2,407 +2,407 @@
 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
     <url>
          <loc>None</loc>
-         <lastmod>2022-04-28</lastmod>
+         <lastmod>2022-05-04</lastmod>
          <changefreq>daily</changefreq>
     </url>
 </urlset>
\ No newline at end of file
diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz
index 911c4fc8a34021b6a723ca156cd166080131192d..452a577c7f9d4fb3b29b512f529af0668f5aeecc 100644
Binary files a/site/sitemap.xml.gz and b/site/sitemap.xml.gz differ