diff --git a/build/dictionary/mkdocs.dic b/build/dictionary/mkdocs.dic index c37da0643e38c0a345136d290b04a614c4708f90..786b945341bf0d50f860e13a4540bb3fa388f502 100644 Binary files a/build/dictionary/mkdocs.dic and b/build/dictionary/mkdocs.dic differ diff --git a/docs/cozystack/index.md b/docs/cozystack/index.md index 6dc5087b2e40162609c558bccf79bfe055babed7..8bb1eac1ae622f6d146496e5f690ad9875733f79 100644 --- a/docs/cozystack/index.md +++ b/docs/cozystack/index.md @@ -28,4 +28,4 @@ for questions and suggestions. ## Why we use it ? -Without that stack we are not able to properly interact with all cozy apps and data. That's why we are using it. For local developpment we are using the official cozy-stack repo with some packaging updates, and for our test env we are using [Easy cozy](../easycozy/index.md) \ No newline at end of file +Without that stack we are not able to properly interact with all cozy apps and data. That's why we are using it. For local development we are using the official cozy-stack repo with some packaging updates, and for our test env we are using [Easy cozy](../easycozy/index.md) \ No newline at end of file diff --git a/docs/cozystack/local.md b/docs/cozystack/local.md index 8344fb677c92bbaa2c41cc1f974c692aa3a0eb31..3452200fe8f94b9bf1fdb7f610da7b978db2cb9a 100644 --- a/docs/cozystack/local.md +++ b/docs/cozystack/local.md @@ -2,11 +2,11 @@ [Gitlab Repo](https://forge.grandlyon.com/web-et-numerique/llle_project/cozy-stack) -### Why are we clonning the official repo ? +### Why are we cloning the official repo ? Because of some political choice Cozy Cloud are not maintaining there official [docker image](https://hub.docker.com/r/cozy/cozy-app-dev) properly. That's why we have a mirroring version of there official repository with some custom docker configuration improving : -* CouchDb version. Officialy Cozy Cloud use CouchDb 3.2.2, but in there official image it's not the case yet. +* CouchDb version. Officially Cozy Cloud use CouchDb 3.2.2, but in there official image it's not the case yet. ### What change should be done by cozy in order to upgrade there image ? diff --git a/docs/ecolyo/application/release.md b/docs/ecolyo/application/release.md index c233049f727f19b2b8084cc6a8e0225234956839..4c16f6ff71c160070c43e3ecdc09666c37a55ff3 100644 --- a/docs/ecolyo/application/release.md +++ b/docs/ecolyo/application/release.md @@ -46,7 +46,7 @@ git push --follow-tags origin dev Don't forget to add release notes in gitlab in *your project -> repository -> tags -> edit release notes * You can copy paste the last changelogs in the release notes. -### Anotated Tags +### Annotated Tags If you see a bug in the Changelog (the last version doesn't compare without the previous version correctly or you have plenty of undesired commits from previous versions), it means you made something wrong when you pushed your commit (basically you may have made a classical git push instead of git push --follow-tags origin dev), and you tag is not correctly annotated or annotated with the wrong commit. diff --git a/docs/ecolyo/functionalities/challenge.md b/docs/ecolyo/functionalities/challenge.md index f3d27747d1f54d3e45a9c492fa7dfe5ad2a6bc77..373589e97bb410615329ca03aecc91fb560fd57e 100644 --- a/docs/ecolyo/functionalities/challenge.md +++ b/docs/ecolyo/functionalities/challenge.md @@ -171,7 +171,7 @@ Exploration is a feature where the user has to do an action in order to help him 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. +- ACTION : Action within 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. @@ -213,12 +213,12 @@ If the user has completed his profile, the application will purpose him a list o 1. First we look for the action that haven't been done yet 2. We pick only the actions that are available for the user's connected fluids -3. 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_ +3. We pick actions that are applicable 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_ 4. If the list is still smaller than 3 after this, we complete with default actions (This case is rare) -5. 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. +5. Finally, we sort the list of action by efficiency 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. +The accomplishment of an action is only conditioned 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 @@ -230,14 +230,14 @@ We check the most recent period first if it's complete and then we go farther an We also define a threshold for a maximum old period !!! note "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. +If the threshold 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. -!!! info "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." +!!! info "In order to not block the user if a value is missing, 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 diff --git a/docs/ecolyo/functionalities/consumption.md b/docs/ecolyo/functionalities/consumption.md index e3e0915a968d16cd5cfb258bbb71d4ee35f808e9..f0a24b16cd0d58298d0ed20ffadaa20d14f09dd2 100644 --- a/docs/ecolyo/functionalities/consumption.md +++ b/docs/ecolyo/functionalities/consumption.md @@ -2,8 +2,8 @@ Ecolyo allow user to see its consumption in two way: -- globally with the mutlifluid view that displays euro consumption -- more specifcally, fluid by fluid, by selecting the wanted fluid in the submenu +- globally with the multifluid view that displays euro consumption +- more specifically, fluid by fluid, by selecting the wanted fluid in the submenu All consumption information are retrieved and calculated by services from the application. @@ -72,7 +72,7 @@ The component allows the user to navigate through the different fluid views (mul ### Rules -1. If a Konnector is errored or its data is outdated, we show a red cross on the fluid icon +1. If a Konnector is on error or its data is outdated, we show a red cross on the fluid icon 2. If the fluid is not connected we show a "turn on" icon 3. Icons have an active state. (They are coloured when selected) @@ -81,7 +81,7 @@ The component allows the user to navigate through the different fluid views (mul ### 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: +It is split in 3 distinct parts: - The ConsumptionVisualier - The FluidSlides @@ -92,7 +92,7 @@ It is splitted in 3 distinct parts: | Component | Rules | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ConsumptionVisualizer | <ul><li>Calls the _DataloadConsumptionVisualizer_ component that shows the dataload of the selected timeStep and fluid</li><li>For multifluid, we show the total consumption of all connected fluid, and the consumption fluid by fluid, all in €</li><li>We display a message according to the data state as explained in the [DataLoad Consumption Visualizer](./#dataload-consumption-visualizer)</li></ul> | -| 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. | +| FluidSlides | This component calls the fluidSwipe component which is handled by the library _react-swipeable-views_, and allows the user to swipe across 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 @@ -131,7 +131,7 @@ The data state is define in the "ConsumptionFormatter" service following theses ### 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 : +This display appear instead of the traditional one (described below). It is used to display a general message which override the value. Here are the rules : | Condition | Displayed label | Comments | | --- | --- | --- | @@ -200,12 +200,12 @@ The chart scale will adapt to the max load displayed between the _actualData_ an ## Konnector Viewer Card -This component shows the konnector's state and allows the user to connect, delete, or update a konnector +This component shows the konnector state and allows the user to connect, delete, or update a konnector ### Rules - 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 error is a login error (eg: user consent is revoked), 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 19999871b1a1ca6d50250306dcb388beeb129701..02b13cd2313d314ff02d1c7f7fb70fd42e2420b7 100644 --- a/docs/ecolyo/functionalities/dacc.md +++ b/docs/ecolyo/functionalities/dacc.md @@ -4,7 +4,7 @@ What is DACC ? A cozy blackbox where apps can send data in order to be anonymise ## Infrastructure workflow -We have two environements, a dev one and a production. Both of them look like the following schema : +We have two environments, a dev one and a production. Both of them look like the following schema :  @@ -142,9 +142,9 @@ with: | PROFILE_COUNT_MONTHLY | profile-count-monthly | | KONNECTOR_ATTEMPTS_MONTHLY | konnector-attempts-monthly | -### Environnements +### Environments -There is two remote doctypes pointing to two differents mode. `dacc-dev` is used on alpha. +There is two remote doctypes pointing to two different mode. `dacc-dev` is used on alpha. ```json "dacc": { @@ -168,7 +168,7 @@ First you need to modify the service in order to be able to see data in local : .getStackClient() .fetchJSON( 'POST', - environementService.isProduction() + environments.isProduction() ? 'http://localhost:8081' : '/remote/cc.cozycloud.dacc.dev', { diff --git a/docs/ecolyo/functionalities/ecogesture.md b/docs/ecolyo/functionalities/ecogesture.md index 3f928a09a699d5ef54b8dd55d00358e76547fb96..3fb87d274d4bb41964feabfdda1cafd8e60f464e 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 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. +- If user chooses 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/initialization.md b/docs/ecolyo/functionalities/initialization.md index 121636138a26365010fa6e8190cee03ca34c2697..3c505e081d10e2e0f8b0d384423b1ae0839aa17d 100644 --- a/docs/ecolyo/functionalities/initialization.md +++ b/docs/ecolyo/functionalities/initialization.md @@ -142,7 +142,7 @@ UserDuelEntity { ### 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 Splash error screnn. +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 Splash error screen. Available loading steps are the followings : diff --git a/docs/ecolyo/functionalities/matomo.md b/docs/ecolyo/functionalities/matomo.md index 7bc746fdbb224dac43c1dee1d2138f6b4b08b767..1319d2996e68b9e04208e9413ed1a15c1b1efec6 100644 --- a/docs/ecolyo/functionalities/matomo.md +++ b/docs/ecolyo/functionalities/matomo.md @@ -19,7 +19,7 @@ _For our development, every alpha instance points to the REC project. That way, ### Matomo server -Matomo is disabled by default on local development to optimize performances. To develop specific features related to matomo withtout having to deploy to alpha, follow theses instructions. +Matomo is disabled by default on local development to optimize performances. To develop specific features related to matomo without having to deploy to alpha, follow theses instructions. ```bash cd docker @@ -38,7 +38,7 @@ On step 5, create a super user with the credentials you want, for example On step6, enter dummy values and select a time zone. -Once you finish the setup and access the server, you should see a warning telling you that matomo has not been configured with the correct port. To fix this problem follow these instrcutions. +Once you finish the setup and access the server, you should see a warning telling you that matomo has not been configured with the correct port. To fix this problem follow these instructions. ``` docker ps # copy container id of matomo diff --git a/docs/ecolyo/functionalities/onboarding.md b/docs/ecolyo/functionalities/onboarding.md index e6559482dff03c0aa911359ebf31058cce0d4749..50460320e5a21a00398142f65c1cce29077cad9d 100644 --- a/docs/ecolyo/functionalities/onboarding.md +++ b/docs/ecolyo/functionalities/onboarding.md @@ -8,7 +8,7 @@ When the user connects for the first time to Ecolyo, onboarding screens will be ### 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. +First of all, we display the GCU screen, which allows user to read the General Condition of Use and the Legal Notice. The user should consent to all the terms to go further in the application. !!! note "About terms" More details are available on the (term section)[/ecolyo/functionalities/terms.md]. diff --git a/docs/ecolyo/functionalities/prices_calculation.md b/docs/ecolyo/functionalities/prices_calculation.md index 1fe4be8eec46e77bca3a0d00d5bf016846552cc0..f4348ec0b9d2683590c5f19374e0c006f5f7aba9 100644 --- a/docs/ecolyo/functionalities/prices_calculation.md +++ b/docs/ecolyo/functionalities/prices_calculation.md @@ -4,8 +4,8 @@ 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 +Since version `1.6.0` of the app, we have a database storing fluid prices evolution since 2012 for the following fluids : +* Electricity * 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. @@ -87,7 +87,7 @@ This service is running every night at 02:00 AM. ### 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. +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 electricity and gas prices. ### New price @@ -102,7 +102,7 @@ In case of price update the following procedure must be done : ### Prices Data -We store in databse a collection of prices with the following info : +We store in database a collection of prices with the following info : * StartDate * EndDate * fluidType @@ -131,7 +131,7 @@ In a shell run a build and test service with le following command line : yarn build-dev:browser; yarn run cozy-konnector-dev -m .\manifest.webapp .\build\services\monthlyReport\ecolyo.js ``` -### Evolutions +### Future Changes We might consider a more dynamic process for fallback price calculation in the future: * Get last price for a given price in database diff --git a/docs/ecolyo/functionalities/profile_type.md b/docs/ecolyo/functionalities/profile_type.md index 7839453a8c186e7451090bf7f6803cb98ba1efbb..dd685426e5db8ee54fd72599b124372ca8c83306 100644 --- a/docs/ecolyo/functionalities/profile_type.md +++ b/docs/ecolyo/functionalities/profile_type.md @@ -164,4 +164,4 @@ Useful tips while working with this API : "source": {} } ``` - - In case of bad request (wrong parameters 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. + - In case of bad request (wrong parameters for example), the API will return an error in _xml_ format so you'll get exactly the same error as above in your cozy instance. diff --git a/docs/ecolyo/functionalities/usage_events_tracking.md b/docs/ecolyo/functionalities/usage_events_tracking.md index 2704c2e78c5b5a733f87676b849aa026acd02894..92d0dddcf4092fb6a478940559447e92110511c9 100644 --- a/docs/ecolyo/functionalities/usage_events_tracking.md +++ b/docs/ecolyo/functionalities/usage_events_tracking.md @@ -32,7 +32,7 @@ All events are stored with the _aggregated_ flag to false to allow the identific ## Usage events aggregator service -## Functionnalities +## Functionalities 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: @@ -75,5 +75,5 @@ 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). +- value: contains aggregated value (example: number of page viewed on a day). - groups: contains all other attribute useful for the indicator (example: context, target, result) diff --git a/docs/ecolyo/getting_started/launch_local_application.md b/docs/ecolyo/getting_started/launch_local_application.md index 8b73879971e2c0c2d10c9d1f6788430e2bf7093c..8e846a96378ca73786b3cd5bf8af41062ac1f106 100644 --- a/docs/ecolyo/getting_started/launch_local_application.md +++ b/docs/ecolyo/getting_started/launch_local_application.md @@ -48,7 +48,7 @@ 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](http://cozy.tools:8080/) +Once successful you can launch your local cozy with following url: [Cozy local url](http://cozy.tools:8080/) Local database can also be consulted at the following url: [Cozy local DB](http://localhost:5984/_utils/) @@ -98,8 +98,7 @@ Once it is done, you will be able to use these 2 Konnectors with real accounts. ## Import mock data !!! info "Requirement" - Your dev stack should be running to import the moke data - + Your dev stack should be running to import the mock data First install ACH using yarn : ``` diff --git a/docs/ecolyo/project_architecture/doctypes.md b/docs/ecolyo/project_architecture/doctypes.md index f55485683e3f3b6b98cd49f89bb175bb7245476f..82e365d263abeb934b0b68683abfb566763a0ccc 100644 --- a/docs/ecolyo/project_architecture/doctypes.md +++ b/docs/ecolyo/project_architecture/doctypes.md @@ -139,7 +139,7 @@ This doctype is used to store ecogestures. | efficiency | number | efficiency of the ecogesture | | difficulty | number | difficulty of the ecogesture | | room | Room | room affected by the ecogesture<br><br>_Room enum:_<br>- _ALL = 0_<br>- _BATHROOM = 1_<br>- _KITCHEN = 2_<br>- _LAUNDRY = 3_<br>- _TOILET = 4_ | -| season | Season | season suited to the ecogesture<br><br>_Season enum:_<br>- _NONE = 'Sans saison'_<br>- _WINTER = 'Hiver'_<br>- _SUMMER = 'Eté'_ | +| season | Season | season suited to the ecogesture<br><br>_Season enum:_<br>- _NONE = 'Sans saison'_<br>- _WINTER = 'Hiver'_<br>- _SUMMER = 'Été'_ | | equipment | boolean | used to know if one or more equipment are affected by the ecogesture | | equipmentType | EquipmentType[] | equipment affected by the ecogesture<br><br>_EquipmentType enum:_<br>- _AIR_CONDITIONING = 0_<br>- _COMPUTER = 1_<br>- _MICROWAVE = 2_<br>- _OVEN = 3_<br>- _WASHING_MACHINE = 4_<br>- _DISHWASHER = 5_<br>- _COOKING_PLATES = 6_<br>- _DRYER = 7_<br>- _REFREGIRATOR = 8_<br>- _GARDEN = 9_<br>- _WATER_HEATER = 10_<br>- _FAN = 11_<br>- _CURTAIN = 12_<br>- _INTERNET_BOX = 13_<br>- _VENTILATION = 14_<br>- _FREEZER = 15_<br>- _BOILER = 16_<br>- _HYDRAULIC_HEATING = 17_ | | equipmentInstallation | boolean | used to know if it is required an installation | diff --git a/docs/pilote/Pilote - TS - Back/functionalities/routes.md b/docs/pilote/Pilote - TS - Back/functionalities/routes.md index 8ca6b21c4289ec38d94dbe08daa205cea1dcbbc6..3a5488e5eefb705ab1ecaa1ee766f574e18c9e73 100644 --- a/docs/pilote/Pilote - TS - Back/functionalities/routes.md +++ b/docs/pilote/Pilote - TS - Back/functionalities/routes.md @@ -21,14 +21,14 @@ A swagger documentation can be consulted at [http://localhost:3000/api/doc/](htt - `/api/beneficiaire`: Get all usager known from Postgre database. -- `/api/beneficiaire/create'`: This route 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/create'`: This route is used in order to store Usager domain and his trigger process 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 route 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. +- `/api/beneficiaire/remove'`: This route is used in order to remove Usager domain and his trigger process. 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 +## Add one beneficiary 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" +- Push in Authorization/ 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"} @@ -39,7 +39,7 @@ A swagger documentation can be consulted at [http://localhost:3000/api/doc/](htt # Cozy -- `api/redirect/cozy`: Allow to send information to the cozy-stack in order to run smsProccess on cozy-stask side. +- `api/redirect/cozy`: Allow to send information to the cozy-stack in order to run smsProcess on cozy-stack side. # Users 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 4b74fd76d9b830d22e2706e3227713cbb2a985d8..b7266428dc28d76e8ad3da3b670ed512f1a2cb92 100644 --- a/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md +++ b/docs/pilote/Pilote - Usager/getting_started/launch_local_doctypes.md @@ -74,7 +74,7 @@ await client.getStackClient().fetchJSON('GET','/remote/org.mps.share?token=eyJhb ``` ## POST -1/ In the request file created. Specify the methode and the route to your target URL : +1/ In the request file created. Specify the method and the route to your target URL : POST https://pilote-agent-dev.grandlyon.com/api/auth/token/check Content-Type: application/json 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 76462edb38c829666cbd25e7c7bf81654008d814..064f8f67604852693802a9237f78fc52c3c83d40 100644 --- a/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md +++ b/docs/pilote/Pilote - Usager/getting_started/launch_local_services.md @@ -1,6 +1,6 @@ ### Use services in local ## Configure the cozy-stack on local -In order to be able to use your sercice, follow these steps: +In order to be able to use your service, follow these steps: 1/ clone [cozy-doctypes](https://github.com/cozy/cozy-doctypes) repository into your system. Then, push it into your root project. diff --git a/docs/pilote/index.md b/docs/pilote/index.md index 93f375908f455c156dbd1853a57ff504b43c7b8c..1d239a6dc9f979aafa2537141643c5c8eb638db0 100644 --- a/docs/pilote/index.md +++ b/docs/pilote/index.md @@ -9,7 +9,7 @@ Pilote aims to help people in various administrative processes, allowing them to ##  Repositories -[MPS group](https://forge.grandlyon.com/solidarite/monparcourssocial) contains the following repos: +[MPS group](https://forge.grandlyon.com/solidarite/monparcourssocial) contains the following repositories: * [pilote usager](https://forge.grandlyon.com/solidarite/monparcourssocial/mps-usager) * travailleur social diff --git a/docs/src/dictionary/en-custom.txt b/docs/src/dictionary/en-custom.txt index 851d1e5c1486f423cdb1276e58d2420324727704..75b73dfa068f9aa7d68da35cc8c26669d26f236a 100644 --- a/docs/src/dictionary/en-custom.txt +++ b/docs/src/dictionary/en-custom.txt @@ -359,25 +359,79 @@ visualisé événements totalValue warmingFluid +developement combineReducers +DataloadSectionValue DetailsMonthlyForecast +fluidSwipe +DateTimes +mesureName +lastDataDate FluidForecast +VM MonthlyForecast +dropdown +mailData +createDayDataFiles +sendEmail +DataloadNoValue +AnalysisConsumptionRow +GCU +isWelcomeSeen +createConnection +HasMany +FluidButtons +ConsumptionVisualizer +FluidSlides +FeedbackModal +FluidChart +TimeStepSelector +updateDate applyied +actualData Synapps calculateMonthWaterRawNeeds +december +HasOne +ligne initChallengeEntity +userProfile initDuelEntity +metabase initEcogesture initExplorationEntity +userExploration +UserAction +userActionState +hotwater initQuizEntity +isTrue +quizEntity calculateSpreadNeeds calculateTotalConsumption calculateWarmingCorrectedConsumption onboarding calculateWarmingEstimatedConsumption ActionChangeEvent +impactLevel +Datetime +equipmentType +EquipmentType +equipmentInstallation +questionLabel +answerLabel +savonne +frileux +Timeseries +cron +getMonthMinLoad +valuesArray +usageevents +sendIndicator ActionEndEvent +Été +getEnedisMonthAnalysisData +Hiver KonnectorViewerCard NestJS KonnectorViewerList @@ -438,8 +492,11 @@ getMonthElectricSpecificConsumption getMonthHeating getMonthlyForecast spreadConsumption +DateNavigator ci +comparisonData cicd +ConsumptionFormatter serie ChallengeProgress UserActionEntity @@ -447,7 +504,9 @@ UserChallengeState UserChallengeSuccess UserDuelEntity quizzProgress +dataDelayOffset UserQuiz +userQuiz actionProgress endingDate explorationProgress @@ -724,21 +783,45 @@ onDeleteAccount oauth ok params +sendReportNotification pdl pilote +uncomment pre pce poc +eg processData +TaskJSON profileType +CouchDb proxied +cozyRegistry +pilotecozytoken powershell +async +DataloadConsumptionVisualizer +AuthStrategy +attrs +const +getTrigger +const +sha +statweb +getStackClient +pilotedemo +smsProcess +cgu +LF prettierrc png +ConsumptionView processStartDate getMaxPowerData getHalfHourData agregateMonthAndYearData +submenu +0.1.5-d4bbe7350ecf13d13734f559c538e3c0ee8dc7ae scaleway sendmail sharecode diff --git a/site/404.html b/site/404.html deleted file mode 100644 index d354134c9ed386fd22a482cdb3a0d9967c4ba94c..0000000000000000000000000000000000000000 --- a/site/404.html +++ /dev/null @@ -1,2548 +0,0 @@ - -<!doctype html> -<html lang="en" class="no-js"> - <head> - - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width,initial-scale=1"> - - <meta name="description" content="A Collection of Technical Documentations Related to the Self-Data Grandlyon Projects."> - - - <meta name="author" content="Métropole de Lyon"> - - - <link rel="icon" href="/img/self_data_grdlyon.png"> - <meta name="generator" content="mkdocs-1.3.0, mkdocs-material-8.3.9"> - - - - <title>Self-Data Grandlyon - Technical Docs</title> - - - - <link rel="stylesheet" href="/assets/stylesheets/main.1d29e8d0.min.css"> - - - <link rel="stylesheet" href="/assets/stylesheets/palette.cbb835fc.min.css"> - - - - <meta name="theme-color" content="#ffffff"> - - - - - - - - - - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"> - <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style> - - - - <link rel="stylesheet" href="/stylesheets/extra.css"> - - <script>__md_scope=new URL("/",location),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script> - - - - - - </head> - - - - - - - - <body dir="ltr" data-md-color-scheme="dracula" data-md-color-primary="white" data-md-color-accent="red"> - - - - <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> - <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> - <label class="md-overlay" for="__drawer"></label> - <div data-md-component="skip"> - - </div> - <div data-md-component="announce"> - - </div> - - - - -<header class="md-header" data-md-component="header"> - <nav class="md-header__inner md-grid" aria-label="Header"> - <a href="/." title="Self-Data Grandlyon - Technical Docs" class="md-header__button md-logo" aria-label="Self-Data Grandlyon - Technical Docs" data-md-component="logo"> - - <img src="/img/self_data_grdlyon.png" alt="logo"> - - </a> - <label class="md-header__button md-icon" for="__drawer"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg> - </label> - <div class="md-header__title" data-md-component="header-title"> - <div class="md-header__ellipsis"> - <div class="md-header__topic"> - <span class="md-ellipsis"> - Self-Data Grandlyon - Technical Docs - </span> - </div> - <div class="md-header__topic" data-md-component="header-topic"> - <span class="md-ellipsis"> - - - - </span> - </div> - </div> - </div> - - - - <label class="md-header__button md-icon" for="__search"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> - </label> - <div class="md-search" data-md-component="search" role="dialog"> - <label class="md-search__overlay" for="__search"></label> - <div class="md-search__inner" role="search"> - <form class="md-search__form" name="search"> - <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required> - <label class="md-search__icon md-icon" for="__search"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> - </label> - <nav class="md-search__options" aria-label="Search"> - - <button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg> - </button> - </nav> - - </form> - <div class="md-search__output"> - <div class="md-search__scrollwrap" data-md-scrollfix> - <div class="md-search-result" data-md-component="search-result"> - <div class="md-search-result__meta"> - Initializing search - </div> - <ol class="md-search-result__list"></ol> - </div> - </div> - </div> - </div> -</div> - - - <div class="md-header__source"> - <a href="https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-technical-doc" title="Go to repository" class="md-source" data-md-component="source"> - <div class="md-source__icon md-icon"> - - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> - </div> - <div class="md-source__repository"> - Clone the Project - </div> -</a> - </div> - - </nav> - -</header> - - <div class="md-container" data-md-component="container"> - - - - - -<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs"> - <div class="md-tabs__inner md-grid"> - <ul class="md-tabs__list"> - - - - - - - - - - <li class="md-tabs__item"> - <a href="/." class="md-tabs__link"> - Home - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/easycozy/" class="md-tabs__link"> - Easy Cozy - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/cozystack/" class="md-tabs__link"> - Cozy stack - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/ecolyo/" class="md-tabs__link"> - Ecolyo - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/pilote/" class="md-tabs__link"> - Pilote - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/konnectors/" class="md-tabs__link"> - Konnectors - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="/proxy/description/" class="md-tabs__link"> - Proxy - </a> - </li> - - - - </ul> - </div> -</nav> - - - - <main class="md-main" data-md-component="main"> - <div class="md-main__inner md-grid"> - - - - <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - - - - - -<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0"> - <label class="md-nav__title" for="__drawer"> - <a href="/." title="Self-Data Grandlyon - Technical Docs" class="md-nav__button md-logo" aria-label="Self-Data Grandlyon - Technical Docs" data-md-component="logo"> - - <img src="/img/self_data_grdlyon.png" alt="logo"> - - </a> - Self-Data Grandlyon - Technical Docs - </label> - - <div class="md-nav__source"> - <a href="https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-technical-doc" title="Go to repository" class="md-source" data-md-component="source"> - <div class="md-source__icon md-icon"> - - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> - </div> - <div class="md-source__repository"> - Clone the Project - </div> -</a> - </div> - - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_1" type="checkbox" id="__nav_1" > - - - - - <label class="md-nav__link" for="__nav_1"> - Home - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Home" data-md-level="1"> - <label class="md-nav__title" for="__nav_1"> - <span class="md-nav__icon md-icon"></span> - Home - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/." class="md-nav__link"> - Getting started - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/external_doc/" class="md-nav__link"> - Additional Ressources - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/setup_your_environment/" class="md-nav__link"> - Setup your environment - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" > - - - - - <label class="md-nav__link" for="__nav_2"> - Easy Cozy - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Easy Cozy" data-md-level="1"> - <label class="md-nav__title" for="__nav_2"> - <span class="md-nav__icon md-icon"></span> - Easy Cozy - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/config/" class="md-nav__link"> - Configuration - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/commands/" class="md-nav__link"> - Commands - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/known_errors/" class="md-nav__link"> - Known errors - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/scripts/" class="md-nav__link"> - Scripts - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/easycozy/tips/" class="md-nav__link"> - Tips - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" > - - - - - <label class="md-nav__link" for="__nav_3"> - Cozy stack - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Cozy stack" data-md-level="1"> - <label class="md-nav__title" for="__nav_3"> - <span class="md-nav__icon md-icon"></span> - Cozy stack - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/cozystack/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/cozystack/local/" class="md-nav__link"> - Local Stack - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" > - - - - - <label class="md-nav__link" for="__nav_4"> - Ecolyo - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Ecolyo" data-md-level="1"> - <label class="md-nav__title" for="__nav_4"> - <span class="md-nav__icon md-icon"></span> - Ecolyo - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_2" type="checkbox" id="__nav_4_2" > - - - - - <label class="md-nav__link" for="__nav_4_2"> - Getting started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting started" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_2"> - <span class="md-nav__icon md-icon"></span> - Getting started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/getting_started/launch_local_konnector/" class="md-nav__link"> - Launch a konnector on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_3" type="checkbox" id="__nav_4_3" > - - - - - <label class="md-nav__link" for="__nav_4_3"> - Project Architecture - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Project Architecture" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_3"> - <span class="md-nav__icon md-icon"></span> - Project Architecture - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/project_architecture/architecture/" class="md-nav__link"> - Architecture - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/project_architecture/libraries/" class="md-nav__link"> - Libraries - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/project_architecture/environments/" class="md-nav__link"> - Environments - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/project_architecture/doctypes/" class="md-nav__link"> - Doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/project_architecture/remote_doctypes/" class="md-nav__link"> - Remote Doctypes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_4" type="checkbox" id="__nav_4_4" > - - - - - <label class="md-nav__link" for="__nav_4_4"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_4"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/description/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/gitflow/" class="md-nav__link"> - Gitflow - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/mail/" class="md-nav__link"> - Mail - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/redux/" class="md-nav__link"> - Redux - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/release/" class="md-nav__link"> - Release - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/application/scaffolding/" class="md-nav__link"> - Scaffolding - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_5" type="checkbox" id="__nav_4_5" > - - - - - <label class="md-nav__link" for="__nav_4_5"> - Services - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Services" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_5"> - <span class="md-nav__icon md-icon"></span> - Services - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/services/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/services/monthly_report_notification/" class="md-nav__link"> - Monthly report notification - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/services/aggregator_usage_events/" class="md-nav__link"> - Aggregator usage events - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/services/consumption_alert/" class="md-nav__link"> - Consumption Alert - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/services/enedis_halfhour_monthly_analysis/" class="md-nav__link"> - Enedis Halfhour Monthly Analysis - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_6" type="checkbox" id="__nav_4_6" > - - - - - <label class="md-nav__link" for="__nav_4_6"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_6"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/analysis/" class="md-nav__link"> - Analysis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/challenge/" class="md-nav__link"> - Challenge - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/consumption/" class="md-nav__link"> - Consumption - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/dacc/" class="md-nav__link"> - Dacc - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/ecogesture/" class="md-nav__link"> - Ecogesture - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/feedback/" class="md-nav__link"> - Feedback - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/initialization/" class="md-nav__link"> - Initialization - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/matomo/" class="md-nav__link"> - Matomo - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/onboarding/" class="md-nav__link"> - Onboarding - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/prices_calculation/" class="md-nav__link"> - Price Calculation - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/profile_type/" class="md-nav__link"> - Profile Type - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/terms/" class="md-nav__link"> - Terms - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/functionalities/usage_events_tracking/" class="md-nav__link"> - Usage events tracking - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7" type="checkbox" id="__nav_4_7" > - - - - - <label class="md-nav__link" for="__nav_4_7"> - Ecolyo-Agent - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Ecolyo-Agent" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_7"> - <span class="md-nav__icon md-icon"></span> - Ecolyo-Agent - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/introduction/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_2" type="checkbox" id="__nav_4_7_2" > - - - - - <label class="md-nav__link" for="__nav_4_7_2"> - Getting started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting started" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_2"> - <span class="md-nav__icon md-icon"></span> - Getting started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/getting_started/setup_your_environment/" class="md-nav__link"> - Setup your environment - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/getting_started/libraries/" class="md-nav__link"> - Libraries - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_3" type="checkbox" id="__nav_4_7_3" > - - - - - <label class="md-nav__link" for="__nav_4_7_3"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_3"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/functionalities/general/" class="md-nav__link"> - General - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/functionalities/authentication/" class="md-nav__link"> - Authentication - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/functionalities/routes/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_4" type="checkbox" id="__nav_4_7_4" > - - - - - <label class="md-nav__link" for="__nav_4_7_4"> - Development - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Development" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_4"> - <span class="md-nav__icon md-icon"></span> - Development - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/development/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/development/handle_assets/" class="md-nav__link"> - Handle assets - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/ecolyo/ecolyo-agent/development/backup/" class="md-nav__link"> - Backup - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" > - - - - - <label class="md-nav__link" for="__nav_5"> - Pilote - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote" data-md-level="1"> - <label class="md-nav__title" for="__nav_5"> - <span class="md-nav__icon md-icon"></span> - Pilote - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2" type="checkbox" id="__nav_5_2" > - - - - - <label class="md-nav__link" for="__nav_5_2"> - Pilote - TS - Back - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - TS - Back" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_2"> - <span class="md-nav__icon md-icon"></span> - Pilote - TS - Back - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_1" type="checkbox" id="__nav_5_2_1" > - - - - - <label class="md-nav__link" for="__nav_5_2_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Back/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_2" type="checkbox" id="__nav_5_2_2" > - - - - - <label class="md-nav__link" for="__nav_5_2_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_3" type="checkbox" id="__nav_5_2_3" > - - - - - <label class="md-nav__link" for="__nav_5_2_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/" class="md-nav__link"> - Project Architecture - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3" type="checkbox" id="__nav_5_3" > - - - - - <label class="md-nav__link" for="__nav_5_3"> - Pilote - TS - Front - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - TS - Front" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_3"> - <span class="md-nav__icon md-icon"></span> - Pilote - TS - Front - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_1" type="checkbox" id="__nav_5_3_1" > - - - - - <label class="md-nav__link" for="__nav_5_3_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Front/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_2" type="checkbox" id="__nav_5_3_2" > - - - - - <label class="md-nav__link" for="__nav_5_3_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_3" type="checkbox" id="__nav_5_3_3" > - - - - - <label class="md-nav__link" for="__nav_5_3_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4" type="checkbox" id="__nav_5_4" > - - - - - <label class="md-nav__link" for="__nav_5_4"> - Pilote - Usager - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - Usager" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_4"> - <span class="md-nav__icon md-icon"></span> - Pilote - Usager - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_1" type="checkbox" id="__nav_5_4_1" > - - - - - <label class="md-nav__link" for="__nav_5_4_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/doctypes/" class="md-nav__link"> - Doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/gitflow/" class="md-nav__link"> - Gitflow - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/scaffolding/" class="md-nav__link"> - Scaffolding - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/services/" class="md-nav__link"> - Services - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/application/store/" class="md-nav__link"> - Store - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_2" type="checkbox" id="__nav_5_4_2" > - - - - - <label class="md-nav__link" for="__nav_5_4_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/functionalities/appointments/" class="md-nav__link"> - Appointments - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/functionalities/contact/" class="md-nav__link"> - Contact - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/functionalities/document/" class="md-nav__link"> - Document - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/functionalities/setting/" class="md-nav__link"> - Settings - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/functionalities/cozy-registry/" class="md-nav__link"> - Cozy Registry - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_3" type="checkbox" id="__nav_5_4_3" > - - - - - <label class="md-nav__link" for="__nav_5_4_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/getting_started/launch_local_application/" class="md-nav__link"> - Launch local application - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/" class="md-nav__link"> - Launch local doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/pilote/Pilote%20-%20Usager/getting_started/launch_local_services/" class="md-nav__link"> - Launch local services - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" > - - - - - <label class="md-nav__link" for="__nav_6"> - Konnectors - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Konnectors" data-md-level="1"> - <label class="md-nav__title" for="__nav_6"> - <span class="md-nav__icon md-icon"></span> - Konnectors - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/konnectors/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/konnectors/enedis/" class="md-nav__link"> - Enedis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/konnectors/enedis-sge/" class="md-nav__link"> - Enedis SGE - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/konnectors/grdf/" class="md-nav__link"> - GRDF - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/konnectors/egl/" class="md-nav__link"> - Eau du Grand Lyon - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7" type="checkbox" id="__nav_7" > - - - - - <label class="md-nav__link" for="__nav_7"> - Proxy - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Proxy" data-md-level="1"> - <label class="md-nav__title" for="__nav_7"> - <span class="md-nav__icon md-icon"></span> - Proxy - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/proxy/description/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/proxy/monitoring/" class="md-nav__link"> - Monitoring - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7_3" type="checkbox" id="__nav_7_3" > - - - - - <label class="md-nav__link" for="__nav_7_3"> - Use cases - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Use cases" data-md-level="2"> - <label class="md-nav__title" for="__nav_7_3"> - <span class="md-nav__icon md-icon"></span> - Use cases - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="/proxy/use_cases/enedis/" class="md-nav__link"> - Enedis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="/proxy/use_cases/grdfadict/" class="md-nav__link"> - Grdf Adict - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - </ul> -</nav> - </div> - </div> - </div> - - - - <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - - -<nav class="md-nav md-nav--secondary" aria-label="Table of contents"> - - - - -</nav> - </div> - </div> - </div> - - - <div class="md-content" data-md-component="content"> - <article class="md-content__inner md-typeset"> - - <h1>404 - Not found</h1> - - </article> - - </div> - </div> - - <a href="#" class="md-top md-icon" data-md-component="top" hidden> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg> - Back to top - </a> - - </main> - - <footer class="md-footer"> - - <div class="md-footer-meta md-typeset"> - <div class="md-footer-meta__inner md-grid"> - <div class="md-copyright"> - - - Made with - <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> - Material for MkDocs - </a> - -</div> - - </div> - </div> -</footer> - - </div> - <div class="md-dialog" data-md-component="dialog"> - <div class="md-dialog__inner md-typeset"></div> - </div> - <script id="__config" type="application/json">{"base": "/", "features": ["navigation.tabs", "navigation.top", "navigation.instant"], "search": "/assets/javascripts/workers/search.b97dbffb.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script> - - - <script src="/assets/javascripts/bundle.6c7ad80a.min.js"></script> - - - </body> -</html> \ No newline at end of file diff --git a/site/assets/images/favicon.png b/site/assets/images/favicon.png deleted file mode 100644 index 1cf13b9f9d978896599290a74f77d5dbe7d1655c..0000000000000000000000000000000000000000 Binary files a/site/assets/images/favicon.png and /dev/null differ diff --git a/site/index.html b/site/index.html deleted file mode 100644 index 4171ef0af3498fda14b23408ef40d078433e4bbc..0000000000000000000000000000000000000000 --- a/site/index.html +++ /dev/null @@ -1,2931 +0,0 @@ - -<!doctype html> -<html lang="en" class="no-js"> - <head> - - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width,initial-scale=1"> - - <meta name="description" content="A Collection of Technical Documentations Related to the Self-Data Grandlyon Projects."> - - - <meta name="author" content="Métropole de Lyon"> - - - <link rel="icon" href="img/self_data_grdlyon.png"> - <meta name="generator" content="mkdocs-1.3.0, mkdocs-material-8.3.9"> - - - - <title>Getting started - Self-Data Grandlyon - Technical Docs</title> - - - - <link rel="stylesheet" href="assets/stylesheets/main.1d29e8d0.min.css"> - - - <link rel="stylesheet" href="assets/stylesheets/palette.cbb835fc.min.css"> - - - - <meta name="theme-color" content="#ffffff"> - - - - - - - - - - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"> - <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style> - - - - <link rel="stylesheet" href="stylesheets/extra.css"> - - <script>__md_scope=new URL(".",location),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script> - - - - - - </head> - - - - - - - - <body dir="ltr" data-md-color-scheme="dracula" data-md-color-primary="white" data-md-color-accent="red"> - - - - <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> - <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> - <label class="md-overlay" for="__drawer"></label> - <div data-md-component="skip"> - - - <a href="#_1" class="md-skip"> - Skip to content - </a> - - </div> - <div data-md-component="announce"> - - </div> - - - - -<header class="md-header" data-md-component="header"> - <nav class="md-header__inner md-grid" aria-label="Header"> - <a href="." title="Self-Data Grandlyon - Technical Docs" class="md-header__button md-logo" aria-label="Self-Data Grandlyon - Technical Docs" data-md-component="logo"> - - <img src="img/self_data_grdlyon.png" alt="logo"> - - </a> - <label class="md-header__button md-icon" for="__drawer"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg> - </label> - <div class="md-header__title" data-md-component="header-title"> - <div class="md-header__ellipsis"> - <div class="md-header__topic"> - <span class="md-ellipsis"> - Self-Data Grandlyon - Technical Docs - </span> - </div> - <div class="md-header__topic" data-md-component="header-topic"> - <span class="md-ellipsis"> - - Getting started - - </span> - </div> - </div> - </div> - - - - <label class="md-header__button md-icon" for="__search"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> - </label> - <div class="md-search" data-md-component="search" role="dialog"> - <label class="md-search__overlay" for="__search"></label> - <div class="md-search__inner" role="search"> - <form class="md-search__form" name="search"> - <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required> - <label class="md-search__icon md-icon" for="__search"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> - </label> - <nav class="md-search__options" aria-label="Search"> - - <button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg> - </button> - </nav> - - </form> - <div class="md-search__output"> - <div class="md-search__scrollwrap" data-md-scrollfix> - <div class="md-search-result" data-md-component="search-result"> - <div class="md-search-result__meta"> - Initializing search - </div> - <ol class="md-search-result__list"></ol> - </div> - </div> - </div> - </div> -</div> - - - <div class="md-header__source"> - <a href="https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-technical-doc" title="Go to repository" class="md-source" data-md-component="source"> - <div class="md-source__icon md-icon"> - - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> - </div> - <div class="md-source__repository"> - Clone the Project - </div> -</a> - </div> - - </nav> - -</header> - - <div class="md-container" data-md-component="container"> - - - - - -<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs"> - <div class="md-tabs__inner md-grid"> - <ul class="md-tabs__list"> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="." class="md-tabs__link md-tabs__link--active"> - Home - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="easycozy/" class="md-tabs__link"> - Easy Cozy - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="cozystack/" class="md-tabs__link"> - Cozy stack - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="ecolyo/" class="md-tabs__link"> - Ecolyo - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="pilote/" class="md-tabs__link"> - Pilote - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="konnectors/" class="md-tabs__link"> - Konnectors - </a> - </li> - - - - - - - - - - - - <li class="md-tabs__item"> - <a href="proxy/description/" class="md-tabs__link"> - Proxy - </a> - </li> - - - - </ul> - </div> -</nav> - - - - <main class="md-main" data-md-component="main"> - <div class="md-main__inner md-grid"> - - - - <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - - - - - -<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0"> - <label class="md-nav__title" for="__drawer"> - <a href="." title="Self-Data Grandlyon - Technical Docs" class="md-nav__button md-logo" aria-label="Self-Data Grandlyon - Technical Docs" data-md-component="logo"> - - <img src="img/self_data_grdlyon.png" alt="logo"> - - </a> - Self-Data Grandlyon - Technical Docs - </label> - - <div class="md-nav__source"> - <a href="https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-technical-doc" title="Go to repository" class="md-source" data-md-component="source"> - <div class="md-source__icon md-icon"> - - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg> - </div> - <div class="md-source__repository"> - Clone the Project - </div> -</a> - </div> - - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--active md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_1" type="checkbox" id="__nav_1" checked> - - - - - <label class="md-nav__link" for="__nav_1"> - Home - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Home" data-md-level="1"> - <label class="md-nav__title" for="__nav_1"> - <span class="md-nav__icon md-icon"></span> - Home - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - - <li class="md-nav__item md-nav__item--active"> - - <input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc"> - - - - - - <label class="md-nav__link md-nav__link--active" for="__toc"> - Getting started - <span class="md-nav__icon md-icon"></span> - </label> - - <a href="." class="md-nav__link md-nav__link--active"> - Getting started - </a> - - - -<nav class="md-nav md-nav--secondary" aria-label="Table of contents"> - - - - - - - <label class="md-nav__title" for="__toc"> - <span class="md-nav__icon md-icon"></span> - Table of contents - </label> - <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> - - <li class="md-nav__item"> - <a href="#installing-prerequisites" class="md-nav__link"> - Installing prerequisites - </a> - -</li> - - <li class="md-nav__item"> - <a href="#usage" class="md-nav__link"> - Usage - </a> - - <nav class="md-nav" aria-label="Usage"> - <ul class="md-nav__list"> - - <li class="md-nav__item"> - <a href="#node-nvm" class="md-nav__link"> - Node NVM - </a> - -</li> - - <li class="md-nav__item"> - <a href="#wsl" class="md-nav__link"> - WSL - </a> - - <nav class="md-nav" aria-label="WSL"> - <ul class="md-nav__list"> - - <li class="md-nav__item"> - <a href="#upgrade-to-wsl-2" class="md-nav__link"> - Upgrade to WSL 2 - </a> - -</li> - - <li class="md-nav__item"> - <a href="#install-your-linux-distribution" class="md-nav__link"> - Install your Linux distribution - </a> - -</li> - - <li class="md-nav__item"> - <a href="#setup-your-distribution" class="md-nav__link"> - Setup your distribution - </a> - -</li> - - </ul> - </nav> - -</li> - - </ul> - </nav> - -</li> - - <li class="md-nav__item"> - <a href="#contributing-to-the-documentation" class="md-nav__link"> - Contributing to the documentation - </a> - -</li> - - </ul> - -</nav> - - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="external_doc/" class="md-nav__link"> - Additional Ressources - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="setup_your_environment/" class="md-nav__link"> - Setup your environment - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" > - - - - - <label class="md-nav__link" for="__nav_2"> - Easy Cozy - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Easy Cozy" data-md-level="1"> - <label class="md-nav__title" for="__nav_2"> - <span class="md-nav__icon md-icon"></span> - Easy Cozy - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="easycozy/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="easycozy/config/" class="md-nav__link"> - Configuration - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="easycozy/commands/" class="md-nav__link"> - Commands - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="easycozy/known_errors/" class="md-nav__link"> - Known errors - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="easycozy/scripts/" class="md-nav__link"> - Scripts - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="easycozy/tips/" class="md-nav__link"> - Tips - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" > - - - - - <label class="md-nav__link" for="__nav_3"> - Cozy stack - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Cozy stack" data-md-level="1"> - <label class="md-nav__title" for="__nav_3"> - <span class="md-nav__icon md-icon"></span> - Cozy stack - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="cozystack/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="cozystack/local/" class="md-nav__link"> - Local Stack - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" > - - - - - <label class="md-nav__link" for="__nav_4"> - Ecolyo - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Ecolyo" data-md-level="1"> - <label class="md-nav__title" for="__nav_4"> - <span class="md-nav__icon md-icon"></span> - Ecolyo - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_2" type="checkbox" id="__nav_4_2" > - - - - - <label class="md-nav__link" for="__nav_4_2"> - Getting started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting started" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_2"> - <span class="md-nav__icon md-icon"></span> - Getting started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/getting_started/launch_local_konnector/" class="md-nav__link"> - Launch a konnector on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_3" type="checkbox" id="__nav_4_3" > - - - - - <label class="md-nav__link" for="__nav_4_3"> - Project Architecture - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Project Architecture" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_3"> - <span class="md-nav__icon md-icon"></span> - Project Architecture - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/project_architecture/architecture/" class="md-nav__link"> - Architecture - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/project_architecture/libraries/" class="md-nav__link"> - Libraries - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/project_architecture/environments/" class="md-nav__link"> - Environments - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/project_architecture/doctypes/" class="md-nav__link"> - Doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/project_architecture/remote_doctypes/" class="md-nav__link"> - Remote Doctypes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_4" type="checkbox" id="__nav_4_4" > - - - - - <label class="md-nav__link" for="__nav_4_4"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_4"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/description/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/gitflow/" class="md-nav__link"> - Gitflow - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/mail/" class="md-nav__link"> - Mail - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/redux/" class="md-nav__link"> - Redux - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/release/" class="md-nav__link"> - Release - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/application/scaffolding/" class="md-nav__link"> - Scaffolding - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_5" type="checkbox" id="__nav_4_5" > - - - - - <label class="md-nav__link" for="__nav_4_5"> - Services - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Services" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_5"> - <span class="md-nav__icon md-icon"></span> - Services - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/services/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/services/monthly_report_notification/" class="md-nav__link"> - Monthly report notification - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/services/aggregator_usage_events/" class="md-nav__link"> - Aggregator usage events - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/services/consumption_alert/" class="md-nav__link"> - Consumption Alert - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/services/enedis_halfhour_monthly_analysis/" class="md-nav__link"> - Enedis Halfhour Monthly Analysis - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_6" type="checkbox" id="__nav_4_6" > - - - - - <label class="md-nav__link" for="__nav_4_6"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_6"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/analysis/" class="md-nav__link"> - Analysis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/challenge/" class="md-nav__link"> - Challenge - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/consumption/" class="md-nav__link"> - Consumption - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/dacc/" class="md-nav__link"> - Dacc - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/ecogesture/" class="md-nav__link"> - Ecogesture - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/feedback/" class="md-nav__link"> - Feedback - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/initialization/" class="md-nav__link"> - Initialization - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/matomo/" class="md-nav__link"> - Matomo - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/onboarding/" class="md-nav__link"> - Onboarding - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/prices_calculation/" class="md-nav__link"> - Price Calculation - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/profile_type/" class="md-nav__link"> - Profile Type - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/terms/" class="md-nav__link"> - Terms - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/functionalities/usage_events_tracking/" class="md-nav__link"> - Usage events tracking - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7" type="checkbox" id="__nav_4_7" > - - - - - <label class="md-nav__link" for="__nav_4_7"> - Ecolyo-Agent - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Ecolyo-Agent" data-md-level="2"> - <label class="md-nav__title" for="__nav_4_7"> - <span class="md-nav__icon md-icon"></span> - Ecolyo-Agent - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/introduction/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_2" type="checkbox" id="__nav_4_7_2" > - - - - - <label class="md-nav__link" for="__nav_4_7_2"> - Getting started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting started" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_2"> - <span class="md-nav__icon md-icon"></span> - Getting started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/getting_started/setup_your_environment/" class="md-nav__link"> - Setup your environment - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/getting_started/libraries/" class="md-nav__link"> - Libraries - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_3" type="checkbox" id="__nav_4_7_3" > - - - - - <label class="md-nav__link" for="__nav_4_7_3"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_3"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/functionalities/general/" class="md-nav__link"> - General - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/functionalities/authentication/" class="md-nav__link"> - Authentication - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/functionalities/routes/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4_7_4" type="checkbox" id="__nav_4_7_4" > - - - - - <label class="md-nav__link" for="__nav_4_7_4"> - Development - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Development" data-md-level="3"> - <label class="md-nav__title" for="__nav_4_7_4"> - <span class="md-nav__icon md-icon"></span> - Development - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/development/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/development/handle_assets/" class="md-nav__link"> - Handle assets - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="ecolyo/ecolyo-agent/development/backup/" class="md-nav__link"> - Backup - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" > - - - - - <label class="md-nav__link" for="__nav_5"> - Pilote - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote" data-md-level="1"> - <label class="md-nav__title" for="__nav_5"> - <span class="md-nav__icon md-icon"></span> - Pilote - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2" type="checkbox" id="__nav_5_2" > - - - - - <label class="md-nav__link" for="__nav_5_2"> - Pilote - TS - Back - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - TS - Back" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_2"> - <span class="md-nav__icon md-icon"></span> - Pilote - TS - Back - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_1" type="checkbox" id="__nav_5_2_1" > - - - - - <label class="md-nav__link" for="__nav_5_2_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Back/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_2" type="checkbox" id="__nav_5_2_2" > - - - - - <label class="md-nav__link" for="__nav_5_2_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Back/functionalities/routes/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_2_3" type="checkbox" id="__nav_5_2_3" > - - - - - <label class="md-nav__link" for="__nav_5_2_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_2_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Back/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Back/project_architecture/architecture/" class="md-nav__link"> - Project Architecture - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3" type="checkbox" id="__nav_5_3" > - - - - - <label class="md-nav__link" for="__nav_5_3"> - Pilote - TS - Front - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - TS - Front" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_3"> - <span class="md-nav__icon md-icon"></span> - Pilote - TS - Front - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_1" type="checkbox" id="__nav_5_3_1" > - - - - - <label class="md-nav__link" for="__nav_5_3_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Front/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_2" type="checkbox" id="__nav_5_3_2" > - - - - - <label class="md-nav__link" for="__nav_5_3_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Front/functionalities/functions/" class="md-nav__link"> - Routes - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3_3" type="checkbox" id="__nav_5_3_3" > - - - - - <label class="md-nav__link" for="__nav_5_3_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_3_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20TS%20-%20Front/getting_started/launch_local_application/" class="md-nav__link"> - Launch the application on local - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4" type="checkbox" id="__nav_5_4" > - - - - - <label class="md-nav__link" for="__nav_5_4"> - Pilote - Usager - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Pilote - Usager" data-md-level="2"> - <label class="md-nav__title" for="__nav_5_4"> - <span class="md-nav__icon md-icon"></span> - Pilote - Usager - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_1" type="checkbox" id="__nav_5_4_1" > - - - - - <label class="md-nav__link" for="__nav_5_4_1"> - Application - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Application" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_1"> - <span class="md-nav__icon md-icon"></span> - Application - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/deploy/" class="md-nav__link"> - Deploy - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/doctypes/" class="md-nav__link"> - Doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/gitflow/" class="md-nav__link"> - Gitflow - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/scaffolding/" class="md-nav__link"> - Scaffolding - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/services/" class="md-nav__link"> - Services - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/application/store/" class="md-nav__link"> - Store - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_2" type="checkbox" id="__nav_5_4_2" > - - - - - <label class="md-nav__link" for="__nav_5_4_2"> - Functionalities - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Functionalities" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_2"> - <span class="md-nav__icon md-icon"></span> - Functionalities - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/functionalities/appointments/" class="md-nav__link"> - Appointments - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/functionalities/contact/" class="md-nav__link"> - Contact - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/functionalities/document/" class="md-nav__link"> - Document - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/functionalities/setting/" class="md-nav__link"> - Settings - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/functionalities/cozy-registry/" class="md-nav__link"> - Cozy Registry - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4_3" type="checkbox" id="__nav_5_4_3" > - - - - - <label class="md-nav__link" for="__nav_5_4_3"> - Getting Started - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Getting Started" data-md-level="3"> - <label class="md-nav__title" for="__nav_5_4_3"> - <span class="md-nav__icon md-icon"></span> - Getting Started - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/getting_started/launch_local_application/" class="md-nav__link"> - Launch local application - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/getting_started/launch_local_doctypes/" class="md-nav__link"> - Launch local doctypes - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="pilote/Pilote%20-%20Usager/getting_started/launch_local_services/" class="md-nav__link"> - Launch local services - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" > - - - - - <label class="md-nav__link" for="__nav_6"> - Konnectors - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Konnectors" data-md-level="1"> - <label class="md-nav__title" for="__nav_6"> - <span class="md-nav__icon md-icon"></span> - Konnectors - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="konnectors/" class="md-nav__link"> - Introduction - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="konnectors/enedis/" class="md-nav__link"> - Enedis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="konnectors/enedis-sge/" class="md-nav__link"> - Enedis SGE - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="konnectors/grdf/" class="md-nav__link"> - GRDF - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="konnectors/egl/" class="md-nav__link"> - Eau du Grand Lyon - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7" type="checkbox" id="__nav_7" > - - - - - <label class="md-nav__link" for="__nav_7"> - Proxy - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Proxy" data-md-level="1"> - <label class="md-nav__title" for="__nav_7"> - <span class="md-nav__icon md-icon"></span> - Proxy - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="proxy/description/" class="md-nav__link"> - Description - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="proxy/monitoring/" class="md-nav__link"> - Monitoring - </a> - </li> - - - - - - - - - - - <li class="md-nav__item md-nav__item--nested"> - - - <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7_3" type="checkbox" id="__nav_7_3" > - - - - - <label class="md-nav__link" for="__nav_7_3"> - Use cases - <span class="md-nav__icon md-icon"></span> - </label> - - <nav class="md-nav" aria-label="Use cases" data-md-level="2"> - <label class="md-nav__title" for="__nav_7_3"> - <span class="md-nav__icon md-icon"></span> - Use cases - </label> - <ul class="md-nav__list" data-md-scrollfix> - - - - - - - <li class="md-nav__item"> - <a href="proxy/use_cases/enedis/" class="md-nav__link"> - Enedis - </a> - </li> - - - - - - - - - - <li class="md-nav__item"> - <a href="proxy/use_cases/grdfadict/" class="md-nav__link"> - Grdf Adict - </a> - </li> - - - - - </ul> - </nav> - </li> - - - - - </ul> - </nav> - </li> - - - - </ul> -</nav> - </div> - </div> - </div> - - - - <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - - -<nav class="md-nav md-nav--secondary" aria-label="Table of contents"> - - - - - - - <label class="md-nav__title" for="__toc"> - <span class="md-nav__icon md-icon"></span> - Table of contents - </label> - <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> - - <li class="md-nav__item"> - <a href="#installing-prerequisites" class="md-nav__link"> - Installing prerequisites - </a> - -</li> - - <li class="md-nav__item"> - <a href="#usage" class="md-nav__link"> - Usage - </a> - - <nav class="md-nav" aria-label="Usage"> - <ul class="md-nav__list"> - - <li class="md-nav__item"> - <a href="#node-nvm" class="md-nav__link"> - Node NVM - </a> - -</li> - - <li class="md-nav__item"> - <a href="#wsl" class="md-nav__link"> - WSL - </a> - - <nav class="md-nav" aria-label="WSL"> - <ul class="md-nav__list"> - - <li class="md-nav__item"> - <a href="#upgrade-to-wsl-2" class="md-nav__link"> - Upgrade to WSL 2 - </a> - -</li> - - <li class="md-nav__item"> - <a href="#install-your-linux-distribution" class="md-nav__link"> - Install your Linux distribution - </a> - -</li> - - <li class="md-nav__item"> - <a href="#setup-your-distribution" class="md-nav__link"> - Setup your distribution - </a> - -</li> - - </ul> - </nav> - -</li> - - </ul> - </nav> - -</li> - - <li class="md-nav__item"> - <a href="#contributing-to-the-documentation" class="md-nav__link"> - Contributing to the documentation - </a> - -</li> - - </ul> - -</nav> - </div> - </div> - </div> - - - <div class="md-content" data-md-component="content"> - <article class="md-content__inner md-typeset"> - - - - -<h1 id="_1"></h1> -<p><img alt="selfdata" class="center" src="/img/docshome.png" /></p> -<p>This documentation covers the technical aspects of projects developed by the Grandlyon in cooperation with <a href="https://cozy.io/fr/">Cozy Cloud</a>.</p> -<h2 id="installing-prerequisites">Installing prerequisites</h2> -<p>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 <a href="https://forge.grandlyon.com/web-et-numerique/wiki_web_num">wiki</a> first.</p> -<table> -<thead> -<tr> -<th>Name</th> -<th>Required</th> -<th>Details</th> -</tr> -</thead> -<tbody> -<tr> -<td><a href="https://nodejs.org/en/download/">Node</a></td> -<td>Yes</td> -<td>Node 16 must be installed as it is the version that runs on the official cozystack.</td> -</tr> -<tr> -<td><a href="https://classic.yarnpkg.com/en/docs/install">Yarn</a></td> -<td>Yes</td> -<td>Yarn is our projects package manager.</td> -</tr> -<tr> -<td><a href="https://www.docker.com/get-started">Docker</a></td> -<td>Yes</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> -<td>Yes</td> -<td></td> -</tr> -<tr> -<td><a href=".#wsl">WSL</a></td> -<td>No</td> -<td>Required for windows users.</td> -</tr> -</tbody> -</table> -<h2 id="usage">Usage</h2> -<h3 id="node-nvm">Node NVM</h3> -<p>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 <code>nvm</code> package on windows or <code>n</code> package on linux.</p> -<p><code>console -$ yarn global add nvm</code></p> -<div class="tabbed-set tabbed-alternate" data-tabs="1:4"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Install a version</label><label for="__tabbed_1_2">See installed node versions</label><label for="__tabbed_1_3">Switch to a specific version</label><label for="__tabbed_1_4">Check your current version</label></div> -<div class="tabbed-content"> -<div class="tabbed-block"> -<p><code>console -$ nvm install X.X.X</code></p> -</div> -<div class="tabbed-block"> -<p><code>console -$ nvm list</code></p> -</div> -<div class="tabbed-block"> -<p><code>console -$ nvm use X.X.X</code></p> -</div> -<div class="tabbed-block"> -<p><code>console -$ node -v</code></p> -</div> -</div> -</div> -<h3 id="wsl">WSL</h3> -<p>First open Powershell as administrator and launch the following command:</p> -<p><code>powershell -dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart</code></p> -<p>This command will install WSL on your computer. After this, you'll need to <mark><strong>reboot</strong></mark>.</p> -<h4 id="upgrade-to-wsl-2">Upgrade to WSL 2</h4> -<p>If you're on WSL 1 and want to upgrade to WSL 2, here is the process:</p> -<ol> -<li> -<p>Open an elevated powershell and paste the following command: - <code>powershell - dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart</code></p> -</li> -<li> -<p>Then, enable the Virtual Machine Platform optional feature. - <code>powershell - dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</code></p> -</li> -<li> -<p>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 - <code>console - $ wsl --set-default-version 2</code></p> -</li> -</ol> -<div class="admonition warning"> -<p class="admonition-title">You might see this message after running the command above</p> -<p>WSL 2 requires an update to its kernel component. -For information please visit <a href="https://aka.ms/wsl2kernel">wsl2kernel</a>.</p> -</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>To make sure it's correctly installed and working, you can open Powershell and paste the following command :</p> -<p><code>powershell -wsl.exe --list --running</code></p> -<p>Now you should see the name of your distribution in the list.</p> -<h4 id="setup-your-distribution">Setup your distribution</h4> -<ol> -<li> -<p>Start updating the packages list by typing: - <code>console - $ sudo apt update</code></p> -</li> -<li> -<p>Install nodejs using the apt package manager - <code>console - $ sudo apt install</code></p> -</li> -<li> -<p>To verify the Installation execute the following command: - <code>console - $ nodejs --version</code></p> -</li> -<li> -<p>To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: - <code>console - $ sudo apt install npm</code></p> -</li> -<li> -<p>To verify the npm Install check using the command: - <code>console - $ npm --version</code></p> -</li> -<li> -<p>To Download and Setup Yarn - <code>console - $ sudo apt install yarn</code></p> -</li> -<li> -<p>To check the installed version of Yarn: - <code>console - $ yarn --version</code></p> -</li> -</ol> -<p>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:</p> -<p><code>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</code></p> -<p>Now you should be at least in version <mark>^1.22</mark> and ready to go on.</p> -<h2 id="contributing-to-the-documentation">Contributing to the documentation</h2> -<p>To install and run the documentation on your laptop, follow the steps in the <a href="https://forge.grandlyon.com/web-et-numerique/llle_project/self-data-technical-doc">README</a>. Then:</p> -<ul> -<li>Create a branch for your change</li> -<li>Add documentation pages to <code>docs</code>, and supporting assets to <code>img</code>.</li> -<li>Write some <a href="https://guides.github.com/features/mastering-markdown/">markdown</a></li> -<li>Submit a merge request</li> -</ul> -<p><img alt="europe" class="inline-center-left" src="/img/partners/europe.png" /> -<img alt="auvergne" src="/img/partners/auvergne.png" /></p> - - <hr> -<div class="md-source-file"> - <small> - - Last update: - <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">May 4, 2022</span> - - - </small> -</div> - - - </article> - - </div> - </div> - - <a href="#" class="md-top md-icon" data-md-component="top" hidden> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg> - Back to top - </a> - - </main> - - <footer class="md-footer"> - - - <nav class="md-footer__inner md-grid" aria-label="Footer" > - - - - <a href="external_doc/" class="md-footer__link md-footer__link--next" aria-label="Next: Additional Ressources" rel="next"> - <div class="md-footer__title"> - <div class="md-ellipsis"> - <span class="md-footer__direction"> - Next - </span> - Additional Ressources - </div> - </div> - <div class="md-footer__button md-icon"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg> - </div> - </a> - - </nav> - - <div class="md-footer-meta md-typeset"> - <div class="md-footer-meta__inner md-grid"> - <div class="md-copyright"> - - - Made with - <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> - Material for MkDocs - </a> - -</div> - - </div> - </div> -</footer> - - </div> - <div class="md-dialog" data-md-component="dialog"> - <div class="md-dialog__inner md-typeset"></div> - </div> - <script id="__config" type="application/json">{"base": ".", "features": ["navigation.tabs", "navigation.top", "navigation.instant"], "search": "assets/javascripts/workers/search.b97dbffb.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script> - - - <script src="assets/javascripts/bundle.6c7ad80a.min.js"></script> - - - </body> -</html> \ No newline at end of file diff --git a/site/search/search_index.json b/site/search/search_index.json deleted file mode 100644 index 66ee1773c3a505db99eb41c68b7940a5c08eb369..0000000000000000000000000000000000000000 --- a/site/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"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. console $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version console $ nvm install X.X.X console $ nvm list console $ nvm use X.X.X console $ node -v WSL First open Powershell as administrator and launch the following command: powershell 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: powershell dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart Then, enable the Virtual Machine Platform optional feature. powershell 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 console $ 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 : powershell 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: console $ sudo apt update Install nodejs using the apt package manager console $ sudo apt install To verify the Installation execute the following command: console $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: console $ sudo apt install npm To verify the npm Install check using the command: console $ npm --version To Download and Setup Yarn console $ sudo apt install yarn To check the installed version of Yarn: console $ 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. console $ yarn global add nvm Install a version See installed node versions Switch to a specific version Check your current version console $ nvm install X.X.X console $ nvm list console $ nvm use X.X.X console $ node -v","title":"Node NVM"},{"location":"#wsl","text":"First open Powershell as administrator and launch the following command: powershell 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: powershell dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart Then, enable the Virtual Machine Platform optional feature. powershell 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 console $ 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 : powershell 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: console $ sudo apt update Install nodejs using the apt package manager console $ sudo apt install To verify the Installation execute the following command: console $ nodejs --version To be able to download npm package, you need to install the npm, the Node.js package manager. To do so type: console $ sudo apt install npm To verify the npm Install check using the command: console $ npm --version To Download and Setup Yarn console $ sudo apt install yarn To check the installed version of Yarn: console $ 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 resources Link Details WIKI This wiki covers all the processes and guidelines towards developers. Cozy resources Link Details COZY Full technical documentation for all cozy libraries. MATTERMOST Chat app for exchange between G.Lyon & Cozy.","title":"Additional Ressources"},{"location":"external_doc/#grandlyon-resources","text":"Link Details WIKI This wiki covers all the processes and guidelines towards developers.","title":"Grandlyon resources"},{"location":"external_doc/#cozy-resources","text":"Link Details COZY Full technical documentation for all cozy libraries. MATTERMOST Chat app for exchange between G.Lyon & Cozy.","title":"Cozy resources"},{"location":"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 Extension 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: 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 . Node Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Version 14 & 16 For our projects you will need to have a version manager for node such as n on linux and nvm on windows. Install both 14 and 16 versions. 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":"setup_your_environment/#vscode","text":"","title":"VSCode"},{"location":"setup_your_environment/#install-vscode","text":"Installation for VSCode can be found here: Installation of VSCode .","title":"Install VSCode"},{"location":"setup_your_environment/#extensions","text":"Installation of Extension 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: CSS Peek Auto Rename Tag indent-rainbow TabOut Liveshare (pair programming extension)","title":"Extensions"},{"location":"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":"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":"setup_your_environment/#node","text":"Node.js\u00ae is a JavaScript runtime built on Chrome's V8 JavaScript engine. Version 14 & 16 For our projects you will need to have a version manager for node such as n on linux and nvm on windows. Install both 14 and 16 versions.","title":"Node"},{"location":"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":"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":"setup_your_environment/#install-docker","text":"Installation of Docker can be found here: Installation of Docker .","title":"Install Docker"},{"location":"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":"cozystack/","text":"What is Cozy-Stack It is the core server of the Cozy platform. It consists of a single process, the Cozy stack . Full Cozy-Stack documentation here . The Cozy-Stack is in charge of serving the Web applications users have installed from the application store. It provides its services through a REST API that allows to: create, update, delete documents inside the database; authenticate users and client applications; send emails; launch jobs on the server. Connectors that import data from remote websites are some sort of jobs. Jobs can be one time tasks (sending a message) or periodic tasks. Some jobs, like the connectors, that require executing third party code on the server side, are sandboxed (we use nsjail for now). \u2026 The Cozy-Stack also allows to access the database replication API, allowing to sync documents between the server and local databases, for example in mobile clients. Two authentication methods are available: Web applications running on the server get a session token when the user log in; OAuth2 for other applications. Feel free to open an issue for questions and suggestions. Why we use it ? Without that stack we are not able to properly interact with all cozy apps and data. That's why we are using it. For local developpment we are using the official cozy-stack repo with some packaging updates, and for our test env we are using Easy cozy","title":"Introduction"},{"location":"cozystack/#what-is-cozy-stack","text":"It is the core server of the Cozy platform. It consists of a single process, the Cozy stack . Full Cozy-Stack documentation here . The Cozy-Stack is in charge of serving the Web applications users have installed from the application store. It provides its services through a REST API that allows to: create, update, delete documents inside the database; authenticate users and client applications; send emails; launch jobs on the server. Connectors that import data from remote websites are some sort of jobs. Jobs can be one time tasks (sending a message) or periodic tasks. Some jobs, like the connectors, that require executing third party code on the server side, are sandboxed (we use nsjail for now). \u2026 The Cozy-Stack also allows to access the database replication API, allowing to sync documents between the server and local databases, for example in mobile clients. Two authentication methods are available: Web applications running on the server get a session token when the user log in; OAuth2 for other applications. Feel free to open an issue for questions and suggestions.","title":"What is Cozy-Stack"},{"location":"cozystack/#why-we-use-it","text":"Without that stack we are not able to properly interact with all cozy apps and data. That's why we are using it. For local developpment we are using the official cozy-stack repo with some packaging updates, and for our test env we are using Easy cozy","title":"Why we use it ?"},{"location":"cozystack/local/","text":"Local stack Gitlab Repo Why are we clonning the official repo ? Because of some political choice Cozy Cloud are not maintaining there official docker image properly. That's why we have a mirroring version of there official repository with some custom docker configuration improving : CouchDb version. Officialy Cozy Cloud use CouchDb 3.2.2, but in there official image it's not the case yet. What change should be done by cozy in order to upgrade there image ? Cozy should upgrade there CouchDb version inside there image. But unfortunately, the base image debian:stretch-slim does not support ERLANG/OTP>=19, and CouchDb need at least a version >=20 for their 3.2.2 version, see official doc . As a consequence they should upgrade there base image to at least debian:buster . But this add a new issue, the official binary of couch-db cannot be build on this version according to some missing libraries. That's why we took the shortcut of using an official CouchDb image How to build new version of the stack ? If we want to build a new stack version it's easy ! A manual pipeline has been created. You just need to run the following steps : Run the manual pipeline in CI/CD part of gitlab Enter the requested parameter VERSION and a value (ex: 1.5.7) The image will be automaticaly build based on the branch and store in the registry.","title":"Local Stack"},{"location":"cozystack/local/#local-stack","text":"Gitlab Repo","title":"Local stack"},{"location":"cozystack/local/#why-are-we-clonning-the-official-repo","text":"Because of some political choice Cozy Cloud are not maintaining there official docker image properly. That's why we have a mirroring version of there official repository with some custom docker configuration improving : CouchDb version. Officialy Cozy Cloud use CouchDb 3.2.2, but in there official image it's not the case yet.","title":"Why are we clonning the official repo ?"},{"location":"cozystack/local/#what-change-should-be-done-by-cozy-in-order-to-upgrade-there-image","text":"Cozy should upgrade there CouchDb version inside there image. But unfortunately, the base image debian:stretch-slim does not support ERLANG/OTP>=19, and CouchDb need at least a version >=20 for their 3.2.2 version, see official doc . As a consequence they should upgrade there base image to at least debian:buster . But this add a new issue, the official binary of couch-db cannot be build on this version according to some missing libraries. That's why we took the shortcut of using an official CouchDb image","title":"What change should be done by cozy in order to upgrade there image ?"},{"location":"cozystack/local/#how-to-build-new-version-of-the-stack","text":"If we want to build a new stack version it's easy ! A manual pipeline has been created. You just need to run the following steps : Run the manual pipeline in CI/CD part of gitlab Enter the requested parameter VERSION and a value (ex: 1.5.7) The image will be automaticaly build based on the branch and store in the registry.","title":"How to build new version of the stack ?"},{"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 bash $ 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 ```bash $ 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) has been installed on [name].cozy.self-data.alpha.grandlyon.com ``` Update the version of a konnector ```bash $ 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 ```bash $ 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 ```bash $ 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 ```bash $ cd /root/easy-cozy cozy-stack instances ls $ docker-compose exec cozy ./cozy instances ls ``` Stack Check stack version bash $ 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: bash cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image bash 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":"bash $ 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":"```bash $ cd /easy-cozy","title":"Install a specific version of a konnector"},{"location":"easycozy/commands/#cozy-stack-konnectors-uninstall-konn-domain-url","text":"$ docker-compose exec cozy ./cozy konnectors uninstall grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" grdfgrandlyon has been uninstalled","title":"cozy-stack konnectors uninstall ${konn} --domain ${url}"},{"location":"easycozy/commands/#cozy-stack-konnectors-install-konn-domain-url","text":"$ 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) has been installed on [name].cozy.self-data.alpha.grandlyon.com ```","title":"cozy-stack konnectors install ${konn} --domain ${url}"},{"location":"easycozy/commands/#update-the-version-of-a-konnector","text":"```bash $ cd /easy-cozy","title":"Update the version of a konnector"},{"location":"easycozy/commands/#cozy-stack-konnectors-update-konn-domain-url","text":"$ 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":"cozy-stack konnectors update ${konn} --domain ${url}"},{"location":"easycozy/commands/#run-a-konnector-from-the-stack","text":"```bash $ cd /root/easy-cozy","title":"Run a konnector from the stack"},{"location":"easycozy/commands/#cozy-stack-konnectors-run-konn-domain-url","text":"$ docker-compose exec cozy ./cozy konnectors run grdfgrandlyon --domain \"[name].cozy.self-data.alpha.grandlyon.com\" ```","title":"cozy-stack konnectors run ${konn} --domain ${url}"},{"location":"easycozy/commands/#instance","text":"","title":"Instance"},{"location":"easycozy/commands/#set-log-level-to-debug-for-an-instance","text":"```bash $ cd /root/easy-cozy","title":"Set log level to debug for an instance"},{"location":"easycozy/commands/#cozy-stack-instances-debug-url-true","text":"$ docker-compose exec cozy ./cozy instances debug --domain \"[name].cozy.self-data.alpha.grandlyon.com\" true ```","title":"cozy-stack instances debug ${url} true"},{"location":"easycozy/commands/#list-all-instances","text":"```bash $ cd /root/easy-cozy","title":"List all instances"},{"location":"easycozy/commands/#cozy-stack-instances-ls","text":"$ docker-compose exec cozy ./cozy instances ls ```","title":"cozy-stack instances ls"},{"location":"easycozy/commands/#stack","text":"","title":"Stack"},{"location":"easycozy/commands/#check-stack-version","text":"bash $ 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: bash cd /easy-cozy/build ./build-docker-image.sh Start the container based on the built image bash 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 : py 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: yml 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 : bash 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 : py 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: yml 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 : bash 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 xxxxxxxxxxx Cookie: cozysessid=xxxxxxxxxxx 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 xxxxxxxxxxx -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 xxxxxxxxxxx Cookie: cozysessid=xxxxxxxxxxx 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 xxxxxxxxxxx -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 environment 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 functionality. 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 environment 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: ```","title":"Deploy build to builds branches"},{"location":"ecolyo/application/deploy/#deploy-on-build-test-branch","text":"$ yarn deploy-test","title":"deploy on build-test branch"},{"location":"ecolyo/application/deploy/#deploy-on-build-dev-branch","text":"$ yarn deploy-dev","title":"deploy on build-dev branch"},{"location":"ecolyo/application/deploy/#deploy-on-build-branch","text":"$ yarn deploy ```","title":"deploy on build branch"},{"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 functionality. 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":"Explanation A templating system was needed for the app. In order to make it easy to use and also responsive, two libraries has been used : - Handlebars - 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 easily 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 we 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/#explanation","text":"A templating system was needed for the app. In order to make it easy to use and also responsive, two libraries has been used : - Handlebars - 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 easily build responsive templates.","title":"Explanation"},{"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 we 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 separate 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 separate 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. Conventional 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: ``` [optional scope]: [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 library javascript that allow to handle easily tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and update changelog file. First manually bump the manifest version (for cozy apps) in manifest.webapp and use the following commit format : 'bump manifest version to X.X.X' Then launch the following command : bash yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0) Once it is done execute to push the tagged commit : git push --follow-tags origin dev Don't forget to add release notes in gitlab in *your project -> repository -> tags -> edit release notes * You can copy paste the last changelogs in the release notes. 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/#conventional-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: ``` [optional scope]: [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":"Conventional commit"},{"location":"ecolyo/application/release/#standard-version","text":"Standard-version is library javascript that allow to handle easily tags and changelog file. Just run the following command in order to create a release tag, bump package.json version and update changelog file. First manually bump the manifest version (for cozy apps) in manifest.webapp and use the following commit format : 'bump manifest version to X.X.X' Then launch the following command : bash yarn run release -- --release-as X.X.X # replace with version number (ex: 1.2.0) Once it is done execute to push the tagged commit : git push --follow-tags origin dev Don't forget to add release notes in gitlab in *your project -> repository -> tags -> edit release notes * You can copy paste the last changelogs in the release notes.","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 overridden 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 utilities 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 management 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 overridden 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 utilities 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 management 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","title":".env"},{"location":"ecolyo/ecolyo-agent/development/deploy/#common-settings","text":"HOSTNAME=your_url.com ADMIN_ROLE= * * DEBUG_MODE=false MOCK_OAUTH2=false HTTPS_PORT=1443 IMAGE_FOLDER=image-lib","title":"Common settings"},{"location":"ecolyo/ecolyo-agent/development/deploy/#needed-to-user-oauth2-authentication","text":"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=/","title":"Needed to user OAuth2 authentication :"},{"location":"ecolyo/ecolyo-agent/development/deploy/#access-to-the-database","text":"DATABASE_USER= * * DATABASE_PASSWORD= * DATABASE_NAME=backoffice ```","title":"Access to the database"},{"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 newsletter from Ecolyo Import assets In the rec or prod server, in the folder scripts , there is the following script, named import-convert-assets.sh . ```bash !/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 . ```bash","title":"Import assets"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#binbash","text":"","title":"!/bin/bash"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#get-env-variables","text":". ../.env EMAIL_ASSETS_PATH=\"src/assets/icons/email\" ECOGESTURE_ASSETS_PATH=\"src/assets/icons/visu/ecogesture\" EXPORT_FORMAT=\".png\" pwd=$(pwd)","title":"Get env variables"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#fetch-and-convert-email-assets","text":"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","title":"Fetch and convert email assets"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#fetch-and-convert-ecogesture-assets","text":"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","title":"Fetch and convert ecogesture assets"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#cleanup","text":"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","title":"Cleanup"},{"location":"ecolyo/ecolyo-agent/development/handle_assets/#give-ownership-to-container-user","text":"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":"Give ownership to container user"},{"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 searchable 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 searchable 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 api 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 api 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 project in local with the backend working launch the following command bash 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 Nginx server with a local configuration located in nginx/site.conf To stop it properly use bash 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 bash 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- :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 project in local with the backend working launch the following command bash 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 Nginx server with a local configuration located in nginx/site.conf To stop it properly use bash 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 bash 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- :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 UI. 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 for 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 UI. 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 for 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 Extension 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 Extension 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 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%. 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 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%. 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 beginning 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 question: 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, INCORRECT) 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 userExploration 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 extension of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. jsx 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 management 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 beginning 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 question: 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, INCORRECT) 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 userExploration 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 extension of an ecogesture to which we add an startDate and a userActionState , allowing user to manage the action state depending on user's progress. jsx 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 management 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 consumption 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. 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 gas, 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, gas) 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 additional 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 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","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 consumption 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. 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 gas, 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, gas)","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 additional 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 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","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 js // 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. json \"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) js 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) js 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. This terminal will listen to incoming request sh cd ./scripts node server.js 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 You must see sent indicators in the previously open terminal json { data: '{\"createdBy\":\"ecolyo\",\"measureName\":\"connection-count-monthly\",\"startDate\":\"2021-12-09\",\"value\":3}' } { data: '{\"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 js // 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. json \"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) js 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) js 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. This terminal will listen to incoming request sh cd ./scripts node server.js 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 You must see sent indicators in the previously open terminal json { data: '{\"createdBy\":\"ecolyo\",\"measureName\":\"connection-count-monthly\",\"startDate\":\"2021-12-09\",\"value\":3}' } { data: '{\"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 functionality 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 functionality 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 : js 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 js reader.readAsDataURL(file); and then apply to the result so we send only the encoded part without its headers. js 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 : js 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 js reader.readAsDataURL(file); and then apply to the result so we send only the encoded part without its headers. js 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. json [ { \"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 data 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 . json \"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 : jsx DuelEntity { id: string title: string description: string duration: Duration } Becomes : jsx 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 : jsx UserDuelEntity { id: string title: string description: string duration: Duration threshold: number state: UserDuelState startDate: string | null fluidTypes: FluidType[] userConsumption: number } Data management 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 Splash 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. json [ { \"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 data 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 . json \"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 : jsx DuelEntity { id: string title: string description: string duration: Duration } Becomes : jsx 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 : jsx 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-management-schema","text":"","title":"Data management 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 Splash 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/matomo/","text":"Matomo Matomo is implemented on ecolyo to anonymously track user's navigation and their devices so we understand better how our users use the app. Hosting Matomo is hosted on statweb.com where two projects are available : PROD for live ecolyo apps Work Prod is not yet enabled in live Ecolyo apps. More development and privacy adjustments are needed. REC for every alpha instance For our development, every alpha instance points to the REC project. That way, we work in an environment that is close to our production one. Local testing Matomo server Matomo is disabled by default on local development to optimize performances. To develop specific features related to matomo withtout having to deploy to alpha, follow theses instructions. bash cd docker docker-compose -f docker-compose.matomo.yml up -d Now visit matomo at localhost://9800/index.php and follow the given instructions to setup your matomo. On step 5, create a super user with the credentials you want, for example root Testtest1 On step6, enter dummy values and select a time zone. Once you finish the setup and access the server, you should see a warning telling you that matomo has not been configured with the correct port. To fix this problem follow these instrcutions. ``` docker ps copy container id of matomo docker exec -it [containerID] bash Install vi apt-get update apt-get install vim Edit config.ini.php vi config/config.ini.php ``` and under \"[General]\" add the port 9800 to the following line : trusted_hosts[] = \"localhost:9800\" After reloading, you should be able to login. We need to make one last change for our app to send data to our matomo server. Ecolyo app In the file src/targets/browser/ index.tsx at line 66 comment the dev condition that is preventing the tracker from being initialized. jsx if ( window.Piwik // && !isDev ) { When you navigate inside the Ecolyo app, in the network tab you should see requests to our matomo server \ud83c\udf89\ud83c\udf89\ud83c\udf89","title":"Matomo"},{"location":"ecolyo/functionalities/matomo/#matomo","text":"Matomo is implemented on ecolyo to anonymously track user's navigation and their devices so we understand better how our users use the app.","title":"Matomo"},{"location":"ecolyo/functionalities/matomo/#hosting","text":"Matomo is hosted on statweb.com where two projects are available : PROD for live ecolyo apps Work Prod is not yet enabled in live Ecolyo apps. More development and privacy adjustments are needed. REC for every alpha instance For our development, every alpha instance points to the REC project. That way, we work in an environment that is close to our production one.","title":"Hosting"},{"location":"ecolyo/functionalities/matomo/#local-testing","text":"","title":"Local testing"},{"location":"ecolyo/functionalities/matomo/#matomo-server","text":"Matomo is disabled by default on local development to optimize performances. To develop specific features related to matomo withtout having to deploy to alpha, follow theses instructions. bash cd docker docker-compose -f docker-compose.matomo.yml up -d Now visit matomo at localhost://9800/index.php and follow the given instructions to setup your matomo. On step 5, create a super user with the credentials you want, for example root Testtest1 On step6, enter dummy values and select a time zone. Once you finish the setup and access the server, you should see a warning telling you that matomo has not been configured with the correct port. To fix this problem follow these instrcutions. ``` docker ps","title":"Matomo server"},{"location":"ecolyo/functionalities/matomo/#copy-container-id-of-matomo","text":"docker exec -it [containerID] bash","title":"copy container id of matomo"},{"location":"ecolyo/functionalities/matomo/#install-vi","text":"apt-get update apt-get install vim","title":"Install vi"},{"location":"ecolyo/functionalities/matomo/#edit-configiniphp","text":"vi config/config.ini.php ``` and under \"[General]\" add the port 9800 to the following line : trusted_hosts[] = \"localhost:9800\" After reloading, you should be able to login. We need to make one last change for our app to send data to our matomo server.","title":"Edit config.ini.php"},{"location":"ecolyo/functionalities/matomo/#ecolyo-app","text":"In the file src/targets/browser/ index.tsx at line 66 comment the dev condition that is preventing the tracker from being initialized. jsx if ( window.Piwik // && !isDev ) { When you navigate inside the Ecolyo app, in the network tab you should see requests to our matomo server \ud83c\udf89\ud83c\udf89\ud83c\udf89","title":"Ecolyo app"},{"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 : bash yarn build-dev:browser; yarn run cozy-konnector-dev -m .\\manifest.webapp .\\build\\services\\monthlyReport\\ecolyo.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 : bash yarn build-dev:browser; yarn run cozy-konnector-dev -m .\\manifest.webapp .\\build\\services\\monthlyReport\\ecolyo.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 : jsx { 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 consumption 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 analysis component : jsx { 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 gas 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 gas, 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 calculate 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-station 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, because cozy expects a json response : json { \"status\": \"502\", \"title\": \"Bad Gateway\", \"detail\": \"the content-type for the response is not authorized\", \"source\": {} } In case of bad request (wrong parameters 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 : jsx { 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 consumption 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 analysis component : jsx { 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 gas 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 gas, 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 calculate 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-station 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, because cozy expects a json response : json { \"status\": \"502\", \"title\": \"Bad Gateway\", \"detail\": \"the content-type for the response is not authorized\", \"source\": {} } In case of bad request (wrong parameters 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 management 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-management","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 management"},{"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 xxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxx' 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 xxxxxxxxxxx' const cookie = 'cozysessid=xxxxxxxxxxx' 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 resources 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 developed 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-resources","text":"Please see also the official cozy documentation .","title":"Cozy resources"},{"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 developed 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 gas 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 additional 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 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 gas 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 additional 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 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 environment 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 should 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 - keycloak 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 contains 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 tested in dev environment 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 environment 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 should 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 - keycloak 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 contains 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 tested in dev environment 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 UI. 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 UI. 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: ```bash POST https://API_URL Content-Type: application/json {{data}} ``` Local remote doctype As the doctype is not yet available 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): ```bash 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 bash ${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\": 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: yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: bash docker-compose up Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): bash \"request\": \"POST https://API_URL\\nContent-Type: application/json\\n\\n{{data}}\", Use of remote doctype in the application Add permission in manifest.webapp json \"ecolyo-usage\": { \"type\": \"org.ecolyo.usage\", \"verbs\": [\"GET\", \"POST\"] } Don't forget to add the description Call the remote docType: jsx 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 parameters 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. ```bash 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 : jsx 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: ```bash 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 available 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): ```bash 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 bash ${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\": 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: yaml -v $PWD/cozy-doctypes:/data/cozy-doctypes start the server with the new image: bash docker-compose up Change the content request param in io.cozy.doctypes/org.ecolyo.usage using the db tool ( http://localhost:5984/_utils ): bash \"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 json \"ecolyo-usage\": { \"type\": \"org.ecolyo.usage\", \"verbs\": [\"GET\", \"POST\"] } Don't forget to add the description Call the remote docType: jsx 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 parameters 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. ```bash 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 : jsx 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 consumption. 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 consumption. 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 independent 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 consumption 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 json \"headers\": { { \"AuthKey\": <your-auth-key>, \"Content-Type\": \"application/x-www-form-urlencoded\" } } json \"body\": { \"mode\": \"formdata\" { \"login\": <your-login>, \"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. json { \"codeRetour\": 100, \"libelleRetour\": \"Connect\u00e9\", \"resultatRetour\": { \"num_abt\": toto, \"list_num_abt\": [toto, tata] \"token\": \"xxxxxxxxxxx\" } } Fetch Data In order to get data from the EGL API we have to request the following route : Method : POST Data Route : /getAllAgregatsByAbonnement.aspx ```json \"body\": { \"mode\": \"formdata\" { \"token\": \"897555754A703055397897456568776E32704C3953514F5R\", \"num_abt\": 1895683, \"date_debut\": MM/DD/YYYY, \"date_fin\": MM/DD/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. json { \"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 subtracting 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 to 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 consumption 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 json \"headers\": { { \"AuthKey\": <your-auth-key>, \"Content-Type\": \"application/x-www-form-urlencoded\" } } json \"body\": { \"mode\": \"formdata\" { \"login\": <your-login>, \"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. json { \"codeRetour\": 100, \"libelleRetour\": \"Connect\u00e9\", \"resultatRetour\": { \"num_abt\": toto, \"list_num_abt\": [toto, tata] \"token\": \"xxxxxxxxxxx\" } }","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 ```json \"body\": { \"mode\": \"formdata\" { \"token\": \"897555754A703055397897456568776E32704C3953514F5R\", \"num_abt\": 1895683, \"date_debut\": MM/DD/YYYY, \"date_fin\": MM/DD/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. json { \"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 subtracting 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 to 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-sge/","text":"This konnector fetches consumption 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/ Enedis SGE Konnector This konnector is in a POC state Enedis context The API used by this konnector are the one used by all energy providers (edf, total...), this one is supposed to have a high availability. 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 are proxied by WSO1 api manager. You can find documentation and devportal here . Scaffolding Aggregate.js: file holding method responsible for month and year aggregation parsing.js: contain all methods for xml to json parsing and data formatting 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. 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 provided 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 schema Authentication TODO: Write this part when full implementation will be done. Information 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 : Get user contract 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> Get daily data Get Max Power data Get Half-hour data The same endpoint is used to get the data. The soap body is the following: 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>","title":"Enedis SGE"},{"location":"konnectors/enedis-sge/#enedis-sge-konnector","text":"This konnector is in a POC state","title":"Enedis SGE Konnector"},{"location":"konnectors/enedis-sge/#enedis-context","text":"The API used by this konnector are the one used by all energy providers (edf, total...), this one is supposed to have a high availability. Contrary to enedis oauth konnector, this is a regular auth konnector.","title":"Enedis context"},{"location":"konnectors/enedis-sge/#technical-overview","text":"","title":"Technical overview"},{"location":"konnectors/enedis-sge/#lib-used","text":"xml2js: Lib allowing easy parsing to json easy-soap-request: Lib making soap request","title":"Lib used"},{"location":"konnectors/enedis-sge/#wso2","text":"For now enedis API are proxied by WSO1 api manager. You can find documentation and devportal here .","title":"WSO2"},{"location":"konnectors/enedis-sge/#scaffolding","text":"Aggregate.js: file holding method responsible for month and year aggregation parsing.js: contain all methods for xml to json parsing and data formatting 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, ...)","title":"Scaffolding"},{"location":"konnectors/enedis-sge/#ts-check","text":"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. ts-check The ts-check is none blocking. It will only put information in vs-code ide.","title":"ts-check"},{"location":"konnectors/enedis-sge/#konnector-methods","text":"Method Description start Main method of konnector. Handle global flow and init method with provided 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","title":"Konnector Methods"},{"location":"konnectors/enedis-sge/#dataflow","text":"","title":"Dataflow"},{"location":"konnectors/enedis-sge/#overview","text":"Lien du schema","title":"Overview"},{"location":"konnectors/enedis-sge/#authentication","text":"TODO: Write this part when full implementation will be done. Information required: Name Surname PointID (PDL) Full address","title":"Authentication"},{"location":"konnectors/enedis-sge/#fetch-data","text":"In order to get data from the SGE API we have to request the following route : Get user contract 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> Get daily data Get Max Power data Get Half-hour data The same endpoint is used to get the data. The soap body is the following: 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>","title":"Fetch Data"},{"location":"konnectors/enedis/","text":"This konnector fetches consumption 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 targeted from pre-registered parameters, 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 authentication_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 data, including the usage_point_id (id of user's meter) that will be needed further to fetch user's data. 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 json \"params\": { \"usage_point_id\": <your-usage-point-id>, \"start\": \"YYYY-MM-DD\", \"end\": \"YYYY-MM-DD\", } json \"headers\": { \"Accept\": \"application/json\", \"Authorization\": \"Bearer xxxxxxxxxxx\" } 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 to 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 targeted from pre-registered parameters, 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 authentication_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 data, including the usage_point_id (id of user's meter) that will be needed further to fetch user's data. 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 json \"params\": { \"usage_point_id\": <your-usage-point-id>, \"start\": \"YYYY-MM-DD\", \"end\": \"YYYY-MM-DD\", } json \"headers\": { \"Accept\": \"application/json\", \"Authorization\": \"Bearer xxxxxxxxxxx\" } 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 to 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 consumption 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 targeted from pre-registered parameters, 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 authentication_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 data, including the pce_id (id of user's meter) that will be needed further to fetch user's data. 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 data 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 everything needed in database to fetch data 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 official 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 to 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 targeted from pre-registered parameters, 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 authentication_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 data, including the pce_id (id of user's meter) that will be needed further to fetch user's data. 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 data 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 everything needed in database to fetch data 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 official 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 to 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 MPS group contains the following repos: pilote usager travailleur social backend frontend Requirements Node 16 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":"MPS group contains the following repos: pilote usager travailleur social backend frontend","title":"Repositories"},{"location":"pilote/#requirements","text":"Node 16","title":"Requirements"},{"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 route 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 route 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 route 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 route 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 Copy the template.env into .env To start Pilote application just launch the following command in a terminal : yarn docker-compose -f docker-compose.dev.yml up -d 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":"Copy the template.env into .env To start Pilote application just launch the following command in a terminal : yarn docker-compose -f docker-compose.dev.yml up -d 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/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 Copy the template.env into .env To start Pilote application, make sure the server is running and launch the command in a terminal : yarn start If the application starts successfully you should access to: http://localhost:4200/","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 Copy the template.env into .env To start Pilote application, make sure the server is running and launch the command in a terminal : yarn start If the application starts successfully you should access to: http://localhost:4200/","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 : powershell 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 : powershell 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 : powershell 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 : powershell 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 to store information on back-end TS - [ org.mps.share ]: Required to search on back-end TS Recette [ org.mps.store.rec ]: Required to store information on rec back-end TS [ org.mps.share.rec ]: Required to search on rec back-end TS 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 to store information on back-end TS - [ org.mps.share ]: Required to search on back-end TS Recette [ org.mps.store.rec ]: Required to store information on rec back-end TS [ org.mps.share.rec ]: Required to search on rec back-end TS 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 javascript { 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 javascript { isPublic: false, toast: null, // Manages global messages toasts error: false, // Manages global errors } Appointment javascript { id: '', appointmentDate: '', // ISO string note: { id: '', content: '', createdAt: '', // ISO string }, objectives: [], } UploadDocument javascript { 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":"javascript { 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":"javascript { isPublic: false, toast: null, // Manages global messages toasts error: false, // Manages global errors }","title":"Global"},{"location":"pilote/Pilote%20-%20Usager/application/store/#appointment","text":"javascript { id: '', appointmentDate: '', // ISO string note: { id: '', content: '', createdAt: '', // ISO string }, objectives: [], }","title":"Appointment"},{"location":"pilote/Pilote%20-%20Usager/application/store/#uploaddocument","text":"javascript { 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 profile 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 profile 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 : json { \"_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 : json { \"_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 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 additional 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 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 additional 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=eyJhb...' ) 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: \"eyJhb...\" } ) } 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=eyJhb...' )","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: \"eyJhb...\" } ) } 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(): ```","title":"Configure the cozy-stack on local"},{"location":"pilote/Pilote%20-%20Usager/getting_started/launch_local_services/#add-symbolic-link-to-mps-for-sms-service","text":"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":"add symbolic link to mps for sms service"},{"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 deleted file mode 100644 index 00a8d1415b40f5827ab447960022cc6a5aabb467..0000000000000000000000000000000000000000 --- a/site/sitemap.xml +++ /dev/null @@ -1,428 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> - <url> - <loc>None</loc> - <lastmod>2022-07-25</lastmod> - <changefreq>daily</changefreq> - </url> -</urlset> \ No newline at end of file diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz deleted file mode 100644 index 0ac9cd6af3dbcf84861582c2080a972c7cbf40e5..0000000000000000000000000000000000000000 Binary files a/site/sitemap.xml.gz and /dev/null differ