Coder Social home page Coder Social logo

datagouv / udata-front Goto Github PK

View Code? Open in Web Editor NEW
10.0 10.0 12.0 20.65 MB

udata customizations for data.gouv.fr.

Home Page: https://www.data.gouv.fr/fr/

License: GNU Lesser General Public License v2.1

JavaScript 4.83% Python 13.81% Vue 22.51% Less 5.04% CSS 0.03% HTML 14.89% TypeScript 37.59% MDX 1.29%

udata-front's Introduction

Add a front-end to udata

Notes on this repo

This is a new version of udata-gouvfr This is a udata extension, you should read the udata documentation first.

Compatibility

udata-front requires Python 3.7+ and udata.

Installation

Install udata.

Remain in the same Python virtual environment and install udata-front:

pip install udata-front

Create a local configuration file udata.cfg in your udata directory (or where your UDATA_SETTINGS point out) or modify an existing one as following:

PLUGINS = ['front']
THEME = 'gouvfr'

Theme development

The front-end theme for the public facing website, is split into two parts :

  • The Jinja templates are located inside udata_front/theme/gouvfr/templates.
  • The Less, Vue & other sourcefiles for the front-end are located in theme.

🚀 Getting started

Before you start your developper journey, you have to setup your python and/or javascript development tools.

It is recommended to have a workspace with the following layout:

$WORKSPACE
├── fs
├── udata
│   ├── ...
│   └── setup.py
├── udata-front
│   ├── ...
│   └── setup.py
└── udata.cfg

Modify your local udata.cfg configuration file as following:

PLUGINS = ['front']
THEME = 'gouvfr'

🐍 Python development

🧱 Installing the python dependencies

Prepare a udata development environment.

Note that we're using pip-tools on this repository too.

The following steps use the same Python virtual environment as udata.

Install udata-front in development mode:

cd udata-front
pre-commit install
pip install -e . -r requirements/test.pip -r requirements/develop.pip

NB: the udata.(in|pip) files are used by the CI to stay in sync with udata requirements. You shouldn't need to tinker with them on your local environment, but they might be updated by the CI when you make a Pull Request.

WARNING: if you experience requirements conflicts, and some dependencies were changed on udata, the udata.pip might need to be manually recompiled locally:

pip-compile requirements/udata.in --output-file=requirements/udata.pip
🚩 Starting the python development server

Simply run the udata project with udata-front loaded as a plugin:

cd udata
inv serve

☕ Javascript development

🏗 Installing the javascript dependencies

First, you need to use Node (version 16+) on your platform. You should consider installing NVM which uses the existing .nvmrc.

cd udata-front

nvm install
nvm use

npm install

And voilà ! ✨

🆕 Start the storybook server

If you want to work on Vue or Less files, you can start the storybook server with this command :

npm run storybook

It allows you to work on the front-end only and even mocks the back-end responses.

You can visit their website to learn more about storybook and how to use it.

💪 Starting the javascript development server

Simply run this command in the project directory :

npm start

This will start a development server that will listen to changes and automatically rebuild the project when needed. Note that a webserver is started by Vite (default port is 1234), however we will not be using it as our CSS and JS files will be served by Jinja instead. More on that later.

📦 @datagouv/components

We are using our own package of components. Their sources are in this repository in udata_front/theme/gouvfr/datagouv-components. They are included in udata-front without any build or release required. They are also available on NPM for others to use.

👀 Other dev commands

Finally, we have a bunch of commands to make your life a tad easier.

You can execute udata-front specific tasks from the udata-front directory with invoke. You can list available development commands with:

inv -l

Example commands:

  • i18n: Extract translatable strings
  • i18nc: Compile translations
  • qa: Run a quality report
  • test: Run tests suite

Additionally, you can run javascript-related commands through npm run.

  • build: Builds the final CSS/JS files. You should probably use this one in production.
  • i18n:report: Generates a report of the i18n missing and unused keys
  • i18n:extract: Same as above, but also automatically adds missing keys to translation files
  • start: Get to coding with live reload and things. Same as npm run dev
  • test: Runs the Cypress tests. More on that in the Tests section of this README.

If you encounter any merge conflict with your package-lock.json, you can fix it with NPM:

npm install --package-lock-only

🏰 General architecture

🚜 Jinja2 templates

Because udata is written in Python, its templating engine is Jinja 2. This means that the HTML received by clients is built at runtime, for each request, using templates with {% block %} tags and includes.

Those template are responsible for building the pages using layouts and blocks. Here are a few to get started (in udata_front/theme/gouvfr/templates), from less specific to more specific :

  • raw.html : contains the general html structure exposing a body block where we can write our page's body. This template is also responsible for including the CSS and JS files.
  • base.html : contains some extra html structure exposing a content block for our page's content, and wraps it around the header and footer.
  • header.html and footer.html : standard header and footer block that will appear on each page
  • home.html: the home page template (duh)

🚲 Javascript

In order to add some interactivity to the project, we are using Vue 3 and some good old VanillaJS. The JS assets are compiled in a single index.js file that includes everything for every page. If the bundle size starts to grow a little bit too much, you might need to think about splitting it into separate files for each page.

🖼️ Style

We are using the DSFR to build our front-end components.

In addition we have a nice litle set of CSS Utilities to quickly build custom components, inspired by bootstrap, most of its documentation lives in the css located in theme/less/.

Whenever a components needs some special styling, you can find their corresponding definitions inside theme/less/specific/<component>, it's best if we can avoid having too much specific styling, but sometimes you just really need it.

🛠️ Build tools

This project uses Vite to build and transform our source files into nice bundles for browsers. Its config can be found in the vite.config.ts file.

Vile does multiple custom things in this project :

  • Transform the .ts files into modern Javascript for browsers
  • Transform the less files into modern CSS using PostCSS
  • Copy the static assets when they change (config is in the vite.config.ts)

Vite uses udata_front.egg-info/PKG-INFO version to name files and udata-front uses its version to load the correct one. If you're udata-front version doesn't match the one loaded in the theme, you may have to do a pip install -e . to update the package information.

🏭 Javascript architecture

🏔️ Vue mounting

We are using the full build of VueJS that includes the compiler in order to compile templates directly in the browser.

There is a single VueJS app (in index.ts) that contains every component and plugins. However, this app is mounted multiple times, on each DOM node containing a vuejs class.

This allows us to mount the app only where it's needed, because each subsequent mount is more DOM to compile and thus has an impact on performance. Moreover, mounting to the smallest possible HTML allows us to prevent accidental XSS vulnerability by forbidding users to compile their content with the Vue engine.

In order to allow inter-component communication, a global event bus is available in the global app, under the $bus variable. You can emit events by using $bus.emit('event') and components can listen to events by using $bus.on('event').

👩‍🔬 Tests

Tests are run in a headless browser using Cypress. Test definitions are located in the cypress/integration directory.

Writing tests is very easy thanks to its syntax :

  it("Displays the page title", () => {
    cy.get("h1").should("be.visible");
  });

To run the Cypress tests, you need a few things:

  • A cypress/udata-front-e2e.cfg file:
cp cypress/udata-front-e2e.cfg.example  cypress/udata-front-e2e.cfg
  • Some loaded fixtures needed by the end-to-end tests:
npm run prepare-e2e
  • A local webserver: in another terminal (still in the same Python virtual environment), run the following command in the same Python virtual environment as udata:
npm run serve-e2e

Then, tests can be run using the following command:

npm run test

Cypress also comes with cypress-axe to allow for accessibility automated testing.

udata-front's People

Contributors

noirbizarre avatar gmougeolle avatar maudetes avatar nicolaskempf57 avatar abulte avatar davidbgk avatar pyup-bot avatar quaxsze avatar thibauddauce avatar teleboas avatar taniki avatar romtal avatar jorek57 avatar restuccia avatar crowdin-opendatateam avatar agarrone avatar rkalfane avatar bolinocroustibat avatar jdesboeufs avatar vinyll avatar magopian avatar grischard avatar jphnoel avatar bzg avatar pblayo avatar cake17 avatar tboye avatar mikoa9 avatar l-vincent-l avatar cquest avatar

Stargazers

 avatar Wassim Badreddine avatar Alain Vagner avatar Amédée DERA avatar M_dev_pro avatar Quentin Leroy avatar  avatar  avatar Raphael ATTAL avatar  avatar

Watchers

Thomas Gratier avatar James Cloos avatar  avatar Geoffrey Aldebert avatar  avatar  avatar  avatar  avatar  avatar  avatar

udata-front's Issues

API for data ?

Existe-t-il une API permettant d'accéder/interagir avec un jeu de données unitaire ?

Exception avec datasets/paginator

Bonjour, j'aimerai partir de votre udata-front pour l'adapter a nos besoins.

Une fois deployé, il y a le google bot qui visite des pages comme /en/topics/regions-et-developement-local/datasets, ce qui produit cette exception:

[2022-07-13 10:06:50,870] ERROR in app: Exception on /en/topics/regions-et-developement-local/datasets [GET]
Traceback (most recent call last):
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask_restplus/api.py", line 584, in error_router
    return original_handler(e)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask_restplus/api.py", line 584, in error_router
    return original_handler(e)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/srv/udata_workspace/udata-front/udata_front/views/topic.py", line 31, in datasets
    datasets=[]
  File "/srv/udata_workspace/udata-front/udata_front/theme/__init__.py", line 134, in render
    return render_theme_template(get_theme(theme), template, **context)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask_themes2/__init__.py", line 138, in render_theme_template
    **context)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/templating.py", line 140, in render_template
    ctx.app,
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/flask/templating.py", line 120, in _render
    rv = template.render(context)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/topic/datasets.html", line 5, in top-level template code
    {% set meta = {
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/environment.py", line 1005, in render
    return concat(self.root_render_func(self.new_context(vars)))
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/topic/datasets.html", line 28, in root
    <section class="default">
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/topic/display_base.html", line 35, in root
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/base.html", line 15, in root
    </div>
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/raw.html", line 36, in root
    <img src="//cdn.public.lu/pictures/logos/gov/gov-light.png" srcset="//cdn.public.lu/pictures/logos/gov/gov-light-hdpi.png 1.5x,
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/base.html", line 54, in block_body
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/topic/display_base.html", line 75, in block_content
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/topic/datasets.html", line 64, in block_main_content
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 262, in call
    return __obj(*args, **kwargs)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 570, in __call__
    return self._invoke(arguments, autoescape)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 110, in _invoke
    return original_invoke(self, arguments, autoescape)
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 574, in _invoke
    rv = self._func(*arguments)
  File "/srv/udata_workspace/udata-front/udata_front/theme/gouvfr/templates/macros/paginator.html", line 35, in macro
    <li>
  File "/srv/udata_workspace/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 630, in _fail_with_undefined_error
    raise self._undefined_exception(hint)
jinja2.exceptions.UndefinedError: 'list object' has no attribute 'pages'

J'ai vu dans le code de topic.py que en effet datasets est initialisé comme une liste vide [], mais ceci est passé dans le template du paginator.

J'essaye de comprendre comment résoudre ceci, mais en attendant je pense que je peux aller plus vitte si je vous demande :-) merci

hydra: Refactor des routes d'hydra

Les routes d'hydra sont inconsistentes. Un refactor est nécessaire en gardant les anciennes routes en alias pour assurer la rétrocompatibilité ?

Chemins d'import CSS non compilés

Bonjour,

Je travaille sur u-data-front-kit et je rencontre un petit problème.
En utilisant le composant DsfrBadge avec une icône, cette dernière est appelée ici: url(../../icons/system/fr--info-fill.svg)

Via @gouvfr/dsfr, le chemin est compilé:

  • url(/node_modules/@gouvfr/dsfr/dist/icons/system/fr--info-fill.svg) en dev
  • url(/assets/fr--info-fill.svg) en prod

Cependant, avec @datagouv/component la règle CSS est préfixée par .datagouv-components et le chemin reste inchangé (en dev ou en prod) ce qui donne une 404.

J'ai testé directement avec le repo datagouv-components en ajoutant un badge

<p class="fr-badge fr-badge--info">info</p>

et le résultat est le même.

Merci !

meta theme-static-root n'existe pas dans l'admin

Le widget des reuses montre une image statique du theme "reuse.png"
Le prefix est placeholderUrl qui prend config.theme_static qui vien du
qui n'est pas trouvé parce que le template.html du admin est celui de udata et pas celui de udata-front

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.