From a1aebfff4fd75332f2809ff7e150b96f1fed2cd1 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 27 May 2024 22:03:16 +0200 Subject: [PATCH 01/19] Dash et datatable fonctionnels --- .github/FUNDING.yml | 2 +- .gitignore | 3 +- .pre-commit-config.yaml | 19 + LICENSE | 201 ----- Pipfile | 14 - Pipfile.lock | 348 --------- README.md | 12 +- datasette/inspect-data.json | 18 - datasette/metadata.yaml | 146 ---- datasette/plugins/menu.py | 12 - datasette/plugins/xlsx.py | 75 -- datasette/settings.json | 11 - datasette/static/custom.css | 178 ----- datasette/static/font/Flaticon.eot | Bin 13476 -> 0 bytes datasette/static/font/Flaticon.svg | 445 ----------- datasette/static/font/Flaticon.ttf | Bin 13300 -> 0 bytes datasette/static/font/Flaticon.woff | Bin 8668 -> 0 bytes datasette/static/font/_flaticon.scss | 139 ---- datasette/static/font/flaticon.css | 81 -- datasette/static/font/flaticon.html | 705 ------------------ datasette/static/icons/1024.png | Bin 32397 -> 0 bytes datasette/static/icons/favicon.ico | Bin 32038 -> 0 bytes datasette/static/icons/icon-192x192.png | Bin 11019 -> 0 bytes datasette/static/icons/icon-256x256.png | Bin 10069 -> 0 bytes datasette/static/icons/icon-384x384.png | Bin 23438 -> 0 bytes datasette/static/icons/icon-512x512.png | Bin 20132 -> 0 bytes datasette/static/manifest.webmanifest | 33 - datasette/templates/_close_open_menus.html | 16 - datasette/templates/_codemirror.html | 14 - datasette/templates/_codemirror_foot.html | 38 - .../_description_source_license.html | 30 - datasette/templates/_footer.html | 23 - datasette/templates/_table.html | 34 - datasette/templates/about.html | 3 - datasette/templates/allow_debug.html | 58 -- datasette/templates/base.html | 94 --- datasette/templates/database.html | 113 --- datasette/templates/error.html | 18 - datasette/templates/index.html | 38 - datasette/templates/logout.html | 25 - datasette/templates/messages_debug.html | 27 - datasette/templates/pages/inscription.html | 240 ------ .../templates/pages/mentions-legales.html | 53 -- datasette/templates/pages/versions.html | 98 --- datasette/templates/patterns.html | 495 ------------ datasette/templates/permissions_debug.html | 55 -- datasette/templates/query.html | 87 --- datasette/templates/row.html | 49 -- datasette/templates/show_json.html | 19 - datasette/templates/table.html | 221 ------ pyproject.toml | 17 + scripts/start-datasette.sh | 9 - src/app.py | 40 + 53 files changed, 88 insertions(+), 4268 deletions(-) create mode 100644 .pre-commit-config.yaml delete mode 100644 LICENSE delete mode 100644 Pipfile delete mode 100644 Pipfile.lock delete mode 100644 datasette/inspect-data.json delete mode 100644 datasette/metadata.yaml delete mode 100644 datasette/plugins/menu.py delete mode 100644 datasette/plugins/xlsx.py delete mode 100644 datasette/settings.json delete mode 100644 datasette/static/custom.css delete mode 100644 datasette/static/font/Flaticon.eot delete mode 100644 datasette/static/font/Flaticon.svg delete mode 100644 datasette/static/font/Flaticon.ttf delete mode 100644 datasette/static/font/Flaticon.woff delete mode 100644 datasette/static/font/_flaticon.scss delete mode 100644 datasette/static/font/flaticon.css delete mode 100644 datasette/static/font/flaticon.html delete mode 100644 datasette/static/icons/1024.png delete mode 100644 datasette/static/icons/favicon.ico delete mode 100644 datasette/static/icons/icon-192x192.png delete mode 100644 datasette/static/icons/icon-256x256.png delete mode 100644 datasette/static/icons/icon-384x384.png delete mode 100644 datasette/static/icons/icon-512x512.png delete mode 100644 datasette/static/manifest.webmanifest delete mode 100644 datasette/templates/_close_open_menus.html delete mode 100644 datasette/templates/_codemirror.html delete mode 100644 datasette/templates/_codemirror_foot.html delete mode 100644 datasette/templates/_description_source_license.html delete mode 100644 datasette/templates/_footer.html delete mode 100644 datasette/templates/_table.html delete mode 100644 datasette/templates/about.html delete mode 100644 datasette/templates/allow_debug.html delete mode 100644 datasette/templates/base.html delete mode 100644 datasette/templates/database.html delete mode 100644 datasette/templates/error.html delete mode 100644 datasette/templates/index.html delete mode 100644 datasette/templates/logout.html delete mode 100644 datasette/templates/messages_debug.html delete mode 100644 datasette/templates/pages/inscription.html delete mode 100644 datasette/templates/pages/mentions-legales.html delete mode 100644 datasette/templates/pages/versions.html delete mode 100644 datasette/templates/patterns.html delete mode 100644 datasette/templates/permissions_debug.html delete mode 100644 datasette/templates/query.html delete mode 100644 datasette/templates/row.html delete mode 100644 datasette/templates/show_json.html delete mode 100644 datasette/templates/table.html create mode 100644 pyproject.toml delete mode 100755 scripts/start-datasette.sh create mode 100644 src/app.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 3b9130a..413cd6c 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: ColinMaudry # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: [ColinMaudry] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username diff --git a/.gitignore b/.gitignore index 3997bea..205fb09 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -*.db \ No newline at end of file +*.db +.egg-info diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..2763415 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-ast + - id: check-case-conflict + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black + args: [ --config=pyproject.toml ] + - repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black-jupyter + args: [ --config=pyproject.toml ] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 2b7a2c8..0000000 --- a/Pipfile +++ /dev/null @@ -1,14 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -datasette = "*" -openpyxl = "*" -datasette-cluster-map = {git = "https://github.com/ColinMaudry/datasette-cluster-map.git"} - -[dev-packages] - -[requires] -python_version = "3" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index e003c26..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,348 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "f41809c4a9d8321eb4b3ab4af7c59601e3066356ff054e612e3cdcd2a06a98be" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "aiofiles": { - "hashes": [ - "sha256:1142fa8e80dbae46bb6339573ad4c8c0841358f79c6eb50a493dceca14621bad", - "sha256:9107f1ca0b2a5553987a94a3c9959fe5b491fdf731389aa5b7b1bd0733e32de6" - ], - "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==22.1.0" - }, - "anyio": { - "hashes": [ - "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421", - "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3" - ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.6.2" - }, - "asgi-csrf": { - "hashes": [ - "sha256:6e9d3bddaeac1a8fd33b188fe2abc8271f9085ab7be6e1a7f4d3c9df5d7f741a", - "sha256:e974cffb8a4ab84a28a0088acbf7a4ecc5be4a64f08dcbe19c60dea103da01c0" - ], - "version": "==0.9" - }, - "asgiref": { - "hashes": [ - "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac", - "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506" - ], - "markers": "python_version >= '3.7'", - "version": "==3.6.0" - }, - "certifi": { - "hashes": [ - "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", - "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" - ], - "markers": "python_version >= '3.6'", - "version": "==2022.12.7" - }, - "click": { - "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.3" - }, - "click-default-group-wheel": { - "hashes": [ - "sha256:1599b0b6e0ff63ee806c2cb76593cb8cc73e723cd53532c92bc496dc6fc90e5c", - "sha256:e90da42d92c03e88a12ed0c0b69c8a29afb5d36e3dc8d29c423ba4219e6d7747" - ], - "version": "==1.2.2" - }, - "datasette": { - "hashes": [ - "sha256:7253c244ab35b537b2aa5ac239d24fd101af4a46caef11ee06a727b1db4e64ca", - "sha256:ca30c37e515400b3ba1b07dfe51093238e33baca75ccf3d163645cf5b3c80fd5" - ], - "index": "pypi", - "version": "==0.64.1" - }, - "datasette-cluster-map": { - "git": "https://github.com/ColinMaudry/datasette-cluster-map.git", - "ref": "ab9c0d79448efbd737d9487bfcee227246ef3b87" - }, - "datasette-leaflet": { - "hashes": [ - "sha256:8fd4e634304be392ae6f7de770d4f22b95a37caecd676a35faeb6200da9423bc", - "sha256:fd88c25666e7680b25b4c6e5546bd02c9f5836bbc0fee61042dbb6b93d4139f0" - ], - "markers": "python_version >= '3.6'", - "version": "==0.2.2" - }, - "et-xmlfile": { - "hashes": [ - "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c", - "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada" - ], - "markers": "python_version >= '3.6'", - "version": "==1.1.0" - }, - "h11": { - "hashes": [ - "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", - "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" - ], - "markers": "python_version >= '3.7'", - "version": "==0.14.0" - }, - "httpcore": { - "hashes": [ - "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb", - "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0" - ], - "markers": "python_version >= '3.7'", - "version": "==0.16.3" - }, - "httpx": { - "hashes": [ - "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9", - "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6" - ], - "markers": "python_version >= '3.7'", - "version": "==0.23.3" - }, - "hupper": { - "hashes": [ - "sha256:15c11bd775d8f98095b745b4e658a17c25c86e3b73275cae896ac1c8d533cb18", - "sha256:2ae554e0fb7daf4cbd37a8c7e0419f6974614095a41a4529ad35fe3067b408a4" - ], - "markers": "python_version >= '3.7'", - "version": "==1.11" - }, - "idna": { - "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" - ], - "version": "==3.4" - }, - "itsdangerous": { - "hashes": [ - "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", - "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" - ], - "markers": "python_version >= '3.7'", - "version": "==2.1.2" - }, - "janus": { - "hashes": [ - "sha256:2596ea5482711c1ee3ef2df6c290aaf370a13c55a007826e8f7c32d696d1d00a", - "sha256:df976f2cdcfb034b147a2d51edfc34ff6bfb12d4e2643d3ad0e10de058cb1612" - ], - "markers": "python_version >= '3.7'", - "version": "==1.0.0" - }, - "jinja2": { - "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.2" - }, - "markupsafe": { - "hashes": [ - "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", - "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", - "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", - "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", - "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", - "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", - "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", - "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", - "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", - "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", - "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", - "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", - "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", - "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", - "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", - "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", - "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", - "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", - "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", - "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", - "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", - "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", - "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", - "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", - "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", - "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", - "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", - "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", - "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", - "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", - "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", - "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", - "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", - "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", - "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", - "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", - "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", - "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", - "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", - "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", - "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", - "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", - "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", - "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", - "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", - "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", - "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", - "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", - "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", - "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" - ], - "markers": "python_version >= '3.7'", - "version": "==2.1.2" - }, - "mergedeep": { - "hashes": [ - "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", - "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307" - ], - "markers": "python_version >= '3.6'", - "version": "==1.3.4" - }, - "openpyxl": { - "hashes": [ - "sha256:24d7d361025d186ba91eff58135d50855cf035a84371b891e58fb6eb5125660f", - "sha256:eccedbe1cdd8b2494057e73959b496821141038dbb7eb9266ea59e3f34208231" - ], - "index": "pypi", - "version": "==3.1.0" - }, - "pint": { - "hashes": [ - "sha256:387cf04078dc7dfe4a708033baad54ab61d82ab06c4ee3d4922b1e45d5626067", - "sha256:68afe65665542ee3ec99f69f043b1d39bfe7c6d61b786940157138fd08b838fb" - ], - "markers": "python_version >= '3.8'", - "version": "==0.20.1" - }, - "pluggy": { - "hashes": [ - "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", - "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" - ], - "markers": "python_version >= '3.6'", - "version": "==1.0.0" - }, - "python-multipart": { - "hashes": [ - "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43" - ], - "version": "==0.0.5" - }, - "pyyaml": { - "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" - ], - "markers": "python_version >= '3.6'", - "version": "==6.0" - }, - "rfc3986": { - "extras": [ - "idna2008" - ], - "hashes": [ - "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", - "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" - ], - "version": "==1.5.0" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, - "sniffio": { - "hashes": [ - "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", - "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", - "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" - ], - "markers": "python_version >= '3.7'", - "version": "==4.4.0" - }, - "uvicorn": { - "hashes": [ - "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8", - "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd" - ], - "markers": "python_version >= '3.7'", - "version": "==0.20.0" - } - }, - "develop": {} -} diff --git a/README.md b/README.md index a1d5bee..02ee76e 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,22 @@ Outil d'exploration et de téléchargement des données essentielles de la comma ## Installation et lancement ```shell -pipenv install -pipenv run scripts/start-datasette.sh +python -m venv .venv +source .venv/bin/activate +pip install . +python src/app.py ``` ## Dépôts de code connexes -- [decp-table-schema-utils](https://github.com/ColinMaudry/decp-table-schema-utils) (traitement et publication des données) +- [decp-processing](https://github.com/ColinMaudry/decp-processing) (traitement et publication des données) - [decp-table-schema](https://github.com/ColinMaudry/decp-table-schema) (schéma de données tabulaire) ## Notes de version +### 2.0.0-alpha + +- Data table fonctionnelle + ### 1.5.0 (28/01/2023 - fixation des dépendances Python pour plus de stabilité en cas de réinstallation (Pipfile) diff --git a/datasette/inspect-data.json b/datasette/inspect-data.json deleted file mode 100644 index e37c02e..0000000 --- a/datasette/inspect-data.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db": { - "hash": "e9fe2958f1e9fb97d9b35868dd9985b127f36fb70b75a6f34a7e97769a1cb40d", - "size": 599478272, - "file": "datasette/db.db", - "tables": { - "decp": { - "count": 603271 - }, - "decp-sans-titulaires": { - "count": 527600 - }, - "decp-titulaires": { - "count": 295857 - } - } - } -} \ No newline at end of file diff --git a/datasette/metadata.yaml b/datasette/metadata.yaml deleted file mode 100644 index c92bde0..0000000 --- a/datasette/metadata.yaml +++ /dev/null @@ -1,146 +0,0 @@ ---- -extra_css_urls: -- "/static/custom.css" -title: Exploration et téléchargement des données essentielles de la commande publique - (format tabulaire) -description: Ce site vous permet de filtrer et trier les données sur les marchés publics, - et de télécharger le résultat sous la forme d'un fichier que vous pourrez ouvrir - dans un logiciel de tableur (MS Excel, LibreOffice, OpenOffice). -source: Données essentielles de la commande publique -source_url: https://www.data.gouv.fr/fr/datasets/608c055b35eb4e6ee20eb325/ -license: Licence ouverte -license_url: https://www.etalab.gouv.fr/wp-content/uploads/2014/05/Licence_Ouverte.pdf -databases: - db: - tables: - decp: - title: Marchés et titulaires (= DECP) - description_html: |- - Marché publics et leurs titulaires, données équivalentes au format réglementaire. Une ligne = un titulaire de marché, donc ces données ne sont pas adaptées pour travailler avec les montants de marché ou compter les marchés. - size: 40 - download: https://www.data.gouv.fr/fr/datasets/r/8587fe77-fb31-4155-8753-f6a3c5e0f5c9 - column_labels: - id: Identifiant - uid: Identifiant unique - acheteur.id: SIRET acheteur - acheteur.nom: Nom de l'acheteur - procedure: Procédure d'achat - nature: Nature - dureeMois: Durée du marché (mois) - dateNotification: Date de notification - datePublicationDonnees: Date de publication des données - montant: Montant - objet: Objet - codeCPV: Code CPV - formePrix: Forme du prix - lieuExecution.code: Code du lieu d'exécution - lieuExecution.typeCode: Code du lieu d'exécution (type) - lieuExecution.nom: Nom du lieu d'exécution - titulaire.id: Identifiant du titulaire - titulaire.typeIdentifiant: Identifiant du titulaire (type) - titulaire.denominationSociale: Nom du titulaire - objetModification: Objet de la modification - source: Source des données - donneesActuelles: Données actuelles ? - anomalies: Anomalies - operation_labels: - exact: est égal à - not: est différent de - contains: contient - endswith: finit par - startswith: commence par - gt: est supérieur à (>) - lt: est inférieur à (<) - lte: est inférieur ou égal à (<=) - gte: est supérieur ou égal à (>=) - isnull__1: est vide - notnull__1: n'est pas vide - decp-sans-titulaires: - title: Marchés publics sans leurs titulaires - description_html: Marchés publics sans les titulaires (pas de colonnes titulaire). Une ligne = un marché, donc ces données sont adaptées pour travailler avec les montants de marchés et compter les marchés. - size: 40 - download: https://www.data.gouv.fr/fr/datasets/r/834c14dd-037c-4825-958d-0a841c4777ae - column_labels: - id: Identifiant - uid: Identifiant unique - acheteur.id: SIRET acheteur - acheteur.nom: Nom de l'acheteur - procedure: Procédure d'achat - nature: Nature - dureeMois: Durée du marché (mois) - dateNotification: Date de notification - datePublicationDonnees: Date de publication des données - montant: Montant - objet: Objet - codeCPV: Code CPV - formePrix: Forme du prix - lieuExecution.code: Code du lieu d'exécution - lieuExecution.typeCode: Code du lieu d'exécution (type) - lieuExecution.nom: Nom du lieu d'exécution - objetModification: Objet de la modification - source: Source des données - donneesActuelles: Données actuelles ? - anomalies: Anomalies - operation_labels: - exact: est égal à - not: est différent de - contains: contient - endswith: finit par - startswith: commence par - gt: est supérieur à (>) - lt: est inférieur à (<) - lte: est inférieur ou égal à (<=) - gte: est supérieur ou égal à (>=) - isnull__1: est vide - notnull__1: n'est pas vide - decp-titulaires: - title: Données sur les titulaires et géolocalisation - description_html: Données détaillées sur les titulaires ayant un numéro SIRET, dont leur géolocalisation. Les colonnes formePrix, procedure, objetModification et datePublicationDonnees sont absentes. Une ligne = un titulaire de marché, donc ces données ne sont pas adaptées pour travailler avec les montants de marché ou compter les marchés. - size: 40 - download: https://www.data.gouv.fr/fr/datasets/r/25fcd9e6-ce5a-41a7-b6c0-f140abb2a060 - column_labels: - id: Identifiant - uid: Identifiant unique - acheteur.id: SIRET acheteur - acheteur.nom: Nom de l'acheteur - procedure: Procédure d'achat - nature: Nature - dureeMois: Durée du marché (mois) - dateNotification: Date de notification - datePublicationDonnees: Date de publication des données - montant: Montant - objet: Objet - codeCPV: Code CPV - formePrix: Forme du prix - lieuExecution.code: Code du lieu d'exécution - lieuExecution.typeCode: Code du lieu d'exécution (type) - lieuExecution.nom: Nom du lieu d'exécution - objetModification: Objet de la modification - source: Source des données - donneesActuelles: Données actuelles ? - anomalies: Anomalies - codeAPE: Code APE - departement: Département - categorie: Catégorie - categorieJuridique: Catégorie juridique - categorieJuridiqueLibelle1: Catégorie juridique niveau 1 - categorieJuridiqueLibelle2: Catégorie juridique niveau 2 - etatEtablissement: État établissement - etatEntreprise: État entreprise - longitude: Longitude - latitude: Latitude - titulaire.id: Identifiant du titulaire - titulaire.typeIdentifiant: Identifiant du titulaire (type) - titulaire.denominationSociale: Nom du titulaire - operation_labels: - exact: est égal à - not: est différent de - contains: contient - endswith: finit par - startswith: commence par - gt: est supérieur à (>) - lt: est inférieur à (<) - lte: est inférieur ou égal à (<=) - gte: est supérieur ou égal à (>=) - isnull__1: est vide - notnull__1: n'est pas vide \ No newline at end of file diff --git a/datasette/plugins/menu.py b/datasette/plugins/menu.py deleted file mode 100644 index ddf0b9a..0000000 --- a/datasette/plugins/menu.py +++ /dev/null @@ -1,12 +0,0 @@ -from datasette import hookimpl - -@hookimpl -def menu_links(datasette, actor): - return [ - {"href": "https://teamopendata.org/t/decp-info-les-donnees-de-la-commande-publique-pour-tous-questions-reponses-discussions/2948", "label": "Présentation / FAQ"}, - {"href": "https://github.com/ColinMaudry/decp-table-schema/#documentation-du-sch%C3%A9ma", "label": "Documentation des champs"}, - {"href": "https://github.com/ColinMaudry/decp.info", "label": "Code source"}, - {"href": "/versions", "label": "Notes de version"}, - {"href": "/inscription", "label": "Lettre d'information"}, - {"href": "/mentions-legales", "label": "Mentions légales"} - ] diff --git a/datasette/plugins/xlsx.py b/datasette/plugins/xlsx.py deleted file mode 100644 index 88bf4dd..0000000 --- a/datasette/plugins/xlsx.py +++ /dev/null @@ -1,75 +0,0 @@ -from datasette import hookimpl -from datasette.utils.asgi import Response -from openpyxl import Workbook -from openpyxl.writer.excel import save_virtual_workbook -from openpyxl.cell import WriteOnlyCell -from openpyxl.styles import Alignment, Font, PatternFill -from tempfile import NamedTemporaryFile - - -def render_spreadsheet(rows): - wb = Workbook(write_only=True) - ws = wb.create_sheet() - ws = wb.active - ws.title = "decp" - - columnSpecs = { - 'acheteur.nom': { - 'width': 7, - 'wrapText': True - }, - 'objet': { - 'width': 7, - 'wrapText': True - }, - 'titulaire.denominationSociale': { - 'width': 7, - 'wrapText': True - }, - } - - columns = rows[0].keys() - if columns[0] == "rowid": - columns = columns[1:] - - letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' - - headers = [] - index = 0 - for col in columns : - c = WriteOnlyCell(ws, col) - c.fill = PatternFill("solid", fgColor="DDEFFF") - headers.append(c) - if col in columnSpecs: - ws.column_dimensions[letters[index]].width = columnSpecs[col]['width'] * 5 - else: - ws.column_dimensions[letters[index]].bestFit = True - index = index + 1 - ws.append(headers) - - for row in rows: - wsRow = [] - for col in columns: - c = WriteOnlyCell(ws, row[col]) - if col in columnSpecs : - c.alignment = Alignment(wrapText = columnSpecs[col]['wrapText']) - wsRow.append(c) - ws.append(wsRow) - - with NamedTemporaryFile() as tmp: - wb.save(tmp.name) - tmp.seek(0) - return Response( - tmp.read(), - headers={ - 'Content-Disposition': 'attachment; filename=decp.xlsx', - 'Content-type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - } - ) - - -@hookimpl -def register_output_renderer(): - return {"extension": "xlsx", - "render": render_spreadsheet, - "can_render": lambda: False} diff --git a/datasette/settings.json b/datasette/settings.json deleted file mode 100644 index 72aee1e..0000000 --- a/datasette/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sql_time_limit_ms": 10000, - "max_returned_rows": 50000, - "num_sql_threads": 6, - "default_cache_ttl": 3600, - "max_csv_mb": 0, - "force_https_urls": 1, - "allow_facet": "off", - "suggest_facets": "off", - "template_debug": 1 -} diff --git a/datasette/static/custom.css b/datasette/static/custom.css deleted file mode 100644 index 041a6c7..0000000 --- a/datasette/static/custom.css +++ /dev/null @@ -1,178 +0,0 @@ -section.content > div.table-wrapper { - display: inline-block; -} - -a, a:visited, a:focus, a:active { - color: #276890; - text-decoration: underline; -} - -a:hover { - color: #0c286d; -} - -a.explore { - font-size: 1.6em; -} - -a.nodec { - text-decoration: none; -} - -nav ul { - list-style-type: none; -} - -nav li { - padding: 10px; - border-top: solid 1px #fff; -} - -nav summary { - font-weight: bold; -} - -nav .nav-menu-inner { - padding: 10px 0; -} - -table.rows-and-columns td > div { - max-height: 100px; - font-size: 0.8em; - overflow-y: auto; - overflow-x: hidden; -} - -table.rows-and-columns tr:nth-child(even) { - background-color: #DDEFFF; -} - -h4,.header4 { - text-decoration: none; -} - -table.rows-and-columns td.col-objet > div { - min-width: 140px; -} - -table.rows-and-columns td.col-procedure > div { - min-width: 140px; -} - -td.col-longitude,th.col-longitude,td.col-latitude,th.col-latitude { - display: none; -} - -#sib-container form label { - width: 100%; -} - -.db-table .columns { - font-size: 0.9em; - color: #555; -} - -.db-presentation { - border-left: 10px solid #276890; - padding-left: 10px; - max-width: 1000px; - margin-top: 30px; - font-size: 1.2em; -} - - -.versions ul ul { - margin-left: 22px; -} - -div.select-wrapper { - width: 160px; -} - -div.select-wrapper.filter-op { - width: 160px; -} - - -/* -Flaticon icon font: Flaticon -Creation date: 22/06/2016 15:35 -*/ - -@font-face { -font-family: "Flaticon"; -src: url("./font/Flaticon.eot"); -src: url("./font/Flaticon.eot?#iefix") format("embedded-opentype"), - url("./font/Flaticon.woff") format("woff"), - url("./font/Flaticon.ttf") format("truetype"), - url("./font/Flaticon.svg#Flaticon") format("svg"); -font-weight: normal; -font-style: normal; -} - -@media screen and (-webkit-min-device-pixel-ratio:0) { -@font-face { -font-family: "Flaticon"; -src: url("./font/Flaticon.svg#Flaticon") format("svg"); -} -} - -[class^="flaticon-"]:before, [class*=" flaticon-"]:before, -[class^="flaticon-"]:after, [class*=" flaticon-"]:after { -font-family: Flaticon; - font-size: 20px; -font-style: normal; -font-weight: bold; -margin-left: 20px; -} - -.flaticon-avatar:before { content: "\f100"; } -.flaticon-avatar-1:before { content: "\f101"; } -.flaticon-back:before { content: "\f102"; } -.flaticon-book:before { content: "\f103"; } -.flaticon-cancel:before { content: "\f104"; } -.flaticon-chat:before { content: "\f105"; } -.flaticon-chat-1:before { content: "\f106"; } -.flaticon-chat-2:before { content: "\f107"; } -.flaticon-copy:before { content: "\f108"; } -.flaticon-dislike:before { content: "\f109"; } -.flaticon-download:before { content: "\f10a"; } -.flaticon-download-1:before { content: "\f10b"; } -.flaticon-edit:before { content: "\f10c"; } -.flaticon-envelope:before { content: "\f10d"; } -.flaticon-folder:before { content: "\f10e"; } -.flaticon-garbage:before { content: "\f10f"; } -.flaticon-glasses:before { content: "\f110"; } -.flaticon-hand:before { content: "\f111"; } -.flaticon-headphones:before { content: "\f112"; } -.flaticon-heart:before { content: "\f113"; } -.flaticon-house:before { content: "\f114"; } -.flaticon-like:before { content: "\f115"; } -.flaticon-link:before { content: "\f116"; } -.flaticon-logout:before { content: "\f117"; } -.flaticon-magnifying-glass:before { content: "\f118"; } -.flaticon-monitor:before { content: "\f119"; } -.flaticon-musical-note:before { content: "\f11a"; } -.flaticon-next:before { content: "\f11b"; } -.flaticon-next-1:before { content: "\f11c"; } -.flaticon-padlock:before { content: "\f11d"; } -.flaticon-paper-plane:before { content: "\f11e"; } -.flaticon-phone-call:before { content: "\f11f"; } -.flaticon-photo-camera:before { content: "\f120"; } -.flaticon-pie-chart:before { content: "\f121"; } -.flaticon-piggy-bank:before { content: "\f122"; } -.flaticon-placeholder:before { content: "\f123"; } -.flaticon-printer:before { content: "\f124"; } -.flaticon-reload:before { content: "\f125"; } -.flaticon-settings:before { content: "\f126"; } -.flaticon-settings-1:before { content: "\f127"; } -.flaticon-share:before { content: "\f128"; } -.flaticon-shopping-bag:before { content: "\f129"; } -.flaticon-shopping-cart:before { content: "\f12a"; } -.flaticon-shuffle:before { content: "\f12b"; } -.flaticon-speaker:before { content: "\f12c"; } -.flaticon-star:before { content: "\f12d"; } -.flaticon-tag:before { content: "\f12e"; } -.flaticon-upload:before { content: "\f12f"; } -.flaticon-upload-1:before { content: "\f130"; } -.flaticon-vector:before { content: "\f131"; } diff --git a/datasette/static/font/Flaticon.eot b/datasette/static/font/Flaticon.eot deleted file mode 100644 index d5f80f6558a7051146c98048e69fe2d919f21383..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13476 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 - - - - -Created by FontForge 20120731 at Wed Jun 22 15:35:07 2016 - By root -Created by root with FontForge 2.0 (http://fontforge.sf.net) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/datasette/static/font/Flaticon.ttf b/datasette/static/font/Flaticon.ttf deleted file mode 100644 index 399bb496a70735e3426a209ee7564fb9ceb6d2b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13300 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 LZ*jQze_s9%Tl3^F diff --git a/datasette/static/font/Flaticon.woff b/datasette/static/font/Flaticon.woff deleted file mode 100644 index 6bbf5e6b066d657893b8e44739c2172e3897d0ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8668 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 - - - - - - - Flaticon WebFont - - - - - - - - -
- - Font Demo -
- - -
- -

Instructions

- -
    -
  • - 1Copy the "Fonts" files and CSS files to your website CSS folder. -
  • -
  • - 2Add the CSS link to your website source code on header. - - <head> -
    ... -
    <link rel="stylesheet" type="text/css" href="your_website_domain/css_root/flaticon.css"> -
    ... -
    </head> -
    -
  • - -
  • -

    - 3Use the icon class on "display: inline" elements: -
    - Use example: <i class="flaticon-airplane49"></i> or <span class="flaticon-airplane49"></span> -

  • -
- -
- - - - -
- - -
-
.flaticon-avatar
- -
- -
-
.flaticon-avatar-1
- -
- -
-
.flaticon-back
- -
- -
-
.flaticon-book
- -
- -
-
.flaticon-cancel
- -
- -
-
.flaticon-chat
- -
- -
-
.flaticon-chat-1
- -
- -
-
.flaticon-chat-2
- -
- -
-
.flaticon-copy
- -
- -
-
.flaticon-dislike
- -
- -
-
.flaticon-download
- -
- -
-
.flaticon-download-1
- -
- -
-
.flaticon-edit
- -
- -
-
.flaticon-envelope
- -
- -
-
.flaticon-folder
- -
- -
-
.flaticon-garbage
- -
- -
-
.flaticon-glasses
- -
- -
-
.flaticon-hand
- -
- -
-
.flaticon-headphones
- -
- -
-
.flaticon-heart
- -
- -
-
.flaticon-house
- -
- -
-
.flaticon-like
- -
- -
-
.flaticon-link
- -
- -
-
.flaticon-logout
- -
- -
-
.flaticon-magnifying-glass
- -
- -
-
.flaticon-monitor
- -
- -
-
.flaticon-musical-note
- -
- -
-
.flaticon-next
- -
- -
-
.flaticon-next-1
- -
- -
-
.flaticon-padlock
- -
- -
-
.flaticon-paper-plane
- -
- -
-
.flaticon-phone-call
- -
- -
-
.flaticon-photo-camera
- -
- -
-
.flaticon-pie-chart
- -
- -
-
.flaticon-piggy-bank
- -
- -
-
.flaticon-placeholder
- -
- -
-
.flaticon-printer
- -
- -
-
.flaticon-reload
- -
- -
-
.flaticon-settings
- -
- -
-
.flaticon-settings-1
- -
- -
-
.flaticon-share
- -
- -
-
.flaticon-shopping-bag
- -
- -
-
.flaticon-shopping-cart
- -
- -
-
.flaticon-shuffle
- -
- -
-
.flaticon-speaker
- -
- -
-
.flaticon-star
- -
- -
-
.flaticon-tag
- -
- -
-
.flaticon-upload
- -
- -
-
.flaticon-upload-1
- -
- -
-
.flaticon-vector
- -
- - -
- - - -
- -
License and attribution:
Font generated by flaticon.com. -
-
Copy the Attribution License:
- - - -
- -
- -
Examples:
- -
-

- - <i class="flaticon-avatar"></i> -

-
- -
-

- - <i class="flaticon-avatar-1"></i> -

-
- -
-

- - <i class="flaticon-back"></i> -

-
- -
-

- - <i class="flaticon-book"></i> -

-
- - - -
- - - - - - - \ No newline at end of file diff --git a/datasette/static/icons/1024.png b/datasette/static/icons/1024.png deleted file mode 100644 index 524f1b5bfe9baacceaa013ebca3500284618e393..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32397 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�t zX1lZT1q+$2y2M-42p{g*|C>83y{^61Gl9~z)- zr}F_^FZa1(@ zPgqCf)Bx!;FmfTX12e~Wp?Hz|yqk23{H-SG8wA5}xz04U9HdqiZYW^O7FgvW0wS!Y zaO|BY9IFat`!=5cpW-N!6u9f+JHxjfStezeNN3B$ZblB97d9G1MF>c;Kn$V4z0G2XNF?LoAe_Qg1PjbsWbW z0NETtKqxZiwS?(4UUCEXBjGY5@8*X6jASX|(fC+DmFdIno*da~2AGku%hr@IXQi2K zJNo%XpW)*1*_{P5WpfYQ^KWsBHXxAmiQ1%Qm=0K<8Nr-8FTucPfwq}#5J1@b*l#|K zQ2NVa76TcliC1L>nN%K! zf|F_Ygm(`@PM`SMD<@#!+nzD2Q2GL`d`zjl)+6ri%k7PTKm^KKcDj=Ao%8uWH+L(| zO<#$zqg<5)DdU|CLa82~C?uQ{c_z7q;_@tAq@N(9@Tw{P6k+N%BRN1=NFD+yy4PSY zj~nLRkH2{#7Q(NG5vkU`5+8#n`*P;eUH|BTYi{+ZqX_5)NIvVUN3urSt9?ii*|Wf2 zjX#;_dAs?G7F>uEP*;q{F#FlNxPh#R4FuYl4Wz3Qy%bmLD&~%2?BhcfO3Zg+attutzVYiLQ|xr@!(+VjNj(NA zB+~AsCTKy_=6~cT>rzQ>754JIxB#_%!_NoSD-#o)BJD|JYgKzOeO0y@UVH&g5|KV) zT>rFWuPI=3%1AxWV<_bIN489(C?>^67ELisA|#66s|(Gj zhnB06MBX(lPnaFwN4F&55-t3+bw!8{CR(BA9-7z9LxtM)mToU~G5~AEuwt8~{0n02 zYmeBr@Mh7N_BGB$Ife9nD>FkwlC%%t!fqDaG$s6NJysxMrxD_ZEDB|cC+~ed@Shy} zp4O#KA!wR&J(1-2{zqW= lA5mY)e`@>xcFFXN>xgl#!GEo>2UoWuD9ETt*GQTK|2GR4zC8c{ diff --git a/datasette/static/icons/icon-256x256.png b/datasette/static/icons/icon-256x256.png deleted file mode 100644 index 805a4cf1fcb963ed4e5dd085b94195018b8b7628..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10069 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 -document.body.addEventListener('click', (ev) => { - /* Close any open details elements that this click is outside of */ - var target = ev.target; - var detailsClickedWithin = null; - while (target && target.tagName != 'DETAILS') { - target = target.parentNode; - } - if (target && target.tagName == 'DETAILS') { - detailsClickedWithin = target; - } - Array.from(document.getElementsByTagName('details')).filter( - (details) => details.open && details != detailsClickedWithin - ).forEach(details => details.open = false); -}); - diff --git a/datasette/templates/_codemirror.html b/datasette/templates/_codemirror.html deleted file mode 100644 index a17eaf9..0000000 --- a/datasette/templates/_codemirror.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/datasette/templates/_codemirror_foot.html b/datasette/templates/_codemirror_foot.html deleted file mode 100644 index ee09cff..0000000 --- a/datasette/templates/_codemirror_foot.html +++ /dev/null @@ -1,38 +0,0 @@ - diff --git a/datasette/templates/_description_source_license.html b/datasette/templates/_description_source_license.html deleted file mode 100644 index c24f321..0000000 --- a/datasette/templates/_description_source_license.html +++ /dev/null @@ -1,30 +0,0 @@ -{% if metadata.description_html or metadata.description %} - -{% endif %} -{% if metadata.license or metadata.license_url or metadata.source or metadata.source_url %} -

- {% if metadata.license or metadata.license_url %}Licence des données : - {% if metadata.license_url %} - {{ metadata.license or metadata.license_url }} - {% else %} - {{ metadata.license }} - {% endif %} - {% endif %} - {% if metadata.source or metadata.source_url %}{% if metadata.license or metadata.license_url %}·{% endif %} - Source des données : {% if metadata.source_url %} - - {% endif %}{{ metadata.source or metadata.source_url }}{% if metadata.source_url %}{% endif %} - {% endif %} - {% if metadata.about or metadata.about_url %}{% if metadata.license or metadata.license_url or metadata.source or metadata.source_url %}·{% endif %} - Plus d'informations : {% if metadata.about_url %} - - {% endif %}{{ metadata.about or metadata.about_url }}{% if metadata.about_url %}{% endif %} - {% endif %} -

-{% endif %} diff --git a/datasette/templates/_footer.html b/datasette/templates/_footer.html deleted file mode 100644 index 8e83afc..0000000 --- a/datasette/templates/_footer.html +++ /dev/null @@ -1,23 +0,0 @@ -Propulsé par Datasette - -{% if metadata %} - {% if metadata.license or metadata.license_url %}· Licence des données : - {% if metadata.license_url %} - {{ metadata.license or metadata.license_url }} - {% else %} - {{ metadata.license }} - {% endif %} - {% endif %} - {% if metadata.source or metadata.source_url %}· - Source des données : {% if metadata.source_url %} - - {% endif %}{{ metadata.source or metadata.source_url }}{% if metadata.source_url %}{% endif %} - {% endif %} - · Code source : Github - {% if metadata.about or metadata.about_url %}· - Plus d'informations : {% if metadata.about_url %} - - {% endif %}{{ metadata.about or metadata.about_url }}{% if metadata.about_url %}{% endif %} - {% endif %} - · Mentions légales -{% endif %} diff --git a/datasette/templates/_table.html b/datasette/templates/_table.html deleted file mode 100644 index b10bae4..0000000 --- a/datasette/templates/_table.html +++ /dev/null @@ -1,34 +0,0 @@ -{% if display_rows %} -
- - - - {% for column in display_columns %} - - {% endfor %} - - - - {% for row in display_rows %} - - {% for cell in row %} - - {% endfor %} - - {% endfor %} - -
- {% if not column.sortable %} - {{ metadata.column_labels[column.name] }} - {% else %} - {% if column.name == sort %} - {{ metadata.column_labels[column.name] }} ▼ - {% else %} - {{ metadata.column_labels[column.name] }}{% if column.name == sort_desc %} ▲{% endif %} - {% endif %} - {% endif %} -
{% if cell.column == "titulaire.id" or cell.column == "acheteur.id" %}{{ cell.value }}{% elif cell.column == "codeAPE" %} {{ cell.value }} {% else %}{{ cell.value }}{% endif %}
-
-{% else %} -

0 lignes

-{% endif %} diff --git a/datasette/templates/about.html b/datasette/templates/about.html deleted file mode 100644 index 290fd9d..0000000 --- a/datasette/templates/about.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends "base.html" %} - -

Coucou

diff --git a/datasette/templates/allow_debug.html b/datasette/templates/allow_debug.html deleted file mode 100644 index 0f1b30f..0000000 --- a/datasette/templates/allow_debug.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Debug allow rules{% endblock %} - -{% block extra_head %} - -{% endblock %} - -{% block content %} - -

Debug allow rules

- -

Use this tool to try out different actor and allow combinations. See Defining permissions with "allow" blocks for documentation.

- -
-
-

- -
-
-

- -
-
- -
-
- -{% if error %}

{{ error }}

{% endif %} - -{% if result == "True" %}

Result: allow

{% endif %} - -{% if result == "False" %}

Result: deny

{% endif %} - -{% endblock %} diff --git a/datasette/templates/base.html b/datasette/templates/base.html deleted file mode 100644 index dbf99e5..0000000 --- a/datasette/templates/base.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - {% block title %}{% endblock %} - - - -{% for url in extra_css_urls %} - -{% endfor %} -{% for url in extra_js_urls %} - -{% endfor %} -{% block extra_head %}{% endblock %} - - - - - - - - - - - - - - - - - - -
- -{% block messages %} -{% if show_messages %} - {% for message, message_type in show_messages() %} -

{{ message }}

- {% endfor %} -{% endif %} -{% endblock %} - -
-{% block content %} -{% endblock %} -
- -
{% block footer %}{% include "_footer.html" %}{% endblock %}
- -{% include "_close_open_menus.html" %} - -{% for body_script in body_scripts %} - {{ body_script.script }} -{% endfor %} - -{% if select_templates %}{% endif %} - - diff --git a/datasette/templates/database.html b/datasette/templates/database.html deleted file mode 100644 index 97a99cb..0000000 --- a/datasette/templates/database.html +++ /dev/null @@ -1,113 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ database }}{% endblock %} - -{% block extra_head %} -{{ super() }} -{% include "_codemirror.html" %} -{% endblock %} - -{% block body_class %}db db-{{ database|to_css_class }}{% endblock %} - -{% block nav %} -

- accueil -

- {{ super() }} -{% endblock %} - -{% block content %} - - - - - - - -{% if attached_databases %} -
-

The following databases are attached to this connection, and can be used for cross-database joins:

-
    - {% for db_name in attached_databases %} -
  • {{ db_name }} - tables
  • - {% endfor %} -
-
-{% endif %} - -

decp.info vous permet d'explorer les données à travers différentes vues. Selon que vous soyez plutôt intéressé·e par le montant, les titulaires ou les caractériques d'un marché public, une vue vous sera plus utile qu'une autre.

- -{% for table in tables %} -{% if show_hidden or not table.hidden %} -
-

{{ metadata.tables[table.name].title }}{% if table.private %} 🔒{% endif %}{% if table.hidden %} (hidden){% endif %}

-

Description : {{ metadata.tables[table.name].description_html | safe }} (CSV)

-

Colonnes : {% for column in table.columns %}{{ column }}{% if not loop.last %}, {% endif %}{% endfor %}

-

{% if table.count is none %}{% else %}{{ "{:,}".format(table.count) }} ligne{% if table.count == 1 %}{% else %}s{% endif %}{% endif %}

-
-{% endif %} -{% endfor %} - -{% if hidden_count and not show_hidden %} -

... and {{ "{:,}".format(hidden_count) }} hidden table{% if hidden_count == 1 %}{% else %}s{% endif %}

-{% endif %} - -{% if views %} -

Views

-
    - {% for view in views %} -
  • {{ view.name }}{% if view.private %} 🔒{% endif %}
  • - {% endfor %} -
-{% endif %} - -{% if queries %} -

Queries

- -{% endif %} - - -{% if allow_execute_sql %} -
-

Requête SQL personnalisée

-

-

- - -

-
-{% endif %} - -{% if allow_download %} -

Download SQLite DB: {{ database }}.db {{ format_bytes(size) }}

-{% endif %} - -{% include "_codemirror_foot.html" %} - -{% endblock %} diff --git a/datasette/templates/error.html b/datasette/templates/error.html deleted file mode 100644 index 3aa13ea..0000000 --- a/datasette/templates/error.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{% if title %}{{ title }}{% else %}Error {{ status }}{% endif %}{% endblock %} - -{% block nav %} -

- accueil -

- {{ super() }} -{% endblock %} - -{% block content %} - -

{% if title %}{{ title }}{% else %}Erreur {{ status }}{% endif %}

- -
{{ error }}
- -{% endblock %} diff --git a/datasette/templates/index.html b/datasette/templates/index.html deleted file mode 100644 index ddda39b..0000000 --- a/datasette/templates/index.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ metadata.title or "Datasette" }}: {% for database in databases %}{{ database.name }}{% if not loop.last %}, {% endif %}{% endfor %}{% endblock %} - -{% block body_class %}index{% endblock %} - -{% block content %} -

{{ metadata.title or "Datasette" }}{% if private %} 🔒{% endif %}

- - -

Explorer les données

- -

Présentation / FAQ / discussions

- -

Notes de version

- -

Se tenir informé des nouveautés de decp.info

- -

colin+decp@maudry.com

- - - -{% endblock %} diff --git a/datasette/templates/logout.html b/datasette/templates/logout.html deleted file mode 100644 index 9873867..0000000 --- a/datasette/templates/logout.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Log out{% endblock %} - -{% block nav %} -

- home -

- {{ super() }} -{% endblock %} - -{% block content %} - -

Log out

- -

You are logged in as {{ display_actor(actor) }}

- -
-
- - -
-
- -{% endblock %} diff --git a/datasette/templates/messages_debug.html b/datasette/templates/messages_debug.html deleted file mode 100644 index e0ab9a4..0000000 --- a/datasette/templates/messages_debug.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Debug messages{% endblock %} - -{% block content %} - -

Debug messages

- -

Set a message:

- -
-
- -
- -
- - -
-
- -{% endblock %} diff --git a/datasette/templates/pages/inscription.html b/datasette/templates/pages/inscription.html deleted file mode 100644 index e68dd42..0000000 --- a/datasette/templates/pages/inscription.html +++ /dev/null @@ -1,240 +0,0 @@ -{% extends "base.html" %} -{% block title %}Se tenir informé{% endblock %} -{% block nav %} -

- accueil -

- {{ super() }} -{% endblock %} -{% block content %} - -

Se tenir informé des nouveautés de decp.info

- -

Mentions légales et politique de confidentialité

- - - - - - - - -
-
-
-
- - - - - Il y a eu un problème lors de votre inscription. - -
-
-
-
-
- - - - - Votre inscription à la lettre d'information de decp.info est confirmée ! - -
-
-
-
-
-
-
-
-

Inscrivez-vous à la lettre d'information de decp.info afin d'être informé·e de l'ajout de nouvelles fonctionnalités (2 mails par mois maximum).

-
-
-
-
-
-
-
- - -
- -
-
- - -
-
-
-
-
-
-
- - -
- -
-
- - -
-
-
-
-
-
-
- - -
- -
-
- - -
-
-
-
-
-
-
-
- -
-
- - -
-
-
-
-
-
- - - - - - - - - - -
-

- Nous utilisons Sendinblue en tant que plateforme marketing. En soumettant ce formulaire, vous reconnaissez que les informations que vous allez fournir seront transmises à Sendinblue en sa qualité de processeur de données; et ce conformément à ses - conditions générales d'utilisation. -

-
- -
-
-
- -
-
- - - -
-
-
-
- - - - - - - - - - -{% endblock %} diff --git a/datasette/templates/pages/mentions-legales.html b/datasette/templates/pages/mentions-legales.html deleted file mode 100644 index 8ed79c7..0000000 --- a/datasette/templates/pages/mentions-legales.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "base.html" %} -{% block title %}Mentions légales{% endblock %} -{% block nav %} -

- accueil -

- {{ super() }} -{% endblock %} -{% block content %} - -
- -

Mentions légales

- -

Le site decp.info est édité par Colin Maudry, inscrit au répertoire SIRENE sous le numéro 812 231 132, dont le siège social est situé à Rennes, et dont l'adresse email est colin@maudry.com.

-

Le site est hébergé en France par :

- -

Scaleway par ONLINE, SAS, au capital de 214 410,50 Euros
-Siège social : 8 rue de la ville l'Evêque-75008 PARIS
-RCS Paris B 433 115 904, TVA FR35433115904
-https://www.scaleway.com

- -

Les icônes de la page d'accueil ont été dessinées par Gregor Cresnar de www.flaticon.com

- - -

Vie privée

- -

Les cookies

- - -

Ce site dépose un petit fichier texte (un « cookie ») sur votre ordinateur lorsque vous le consultez (Wikipédia). Cela me permet de mesurer le nombre de visites et de distinguer les nouveaux visiteurs des utilisateurs réguliers.

- -
- -

Ce site n’affiche pas de bannière de consentement aux cookies, pourquoi ?

- -

C’est vrai, vous n’avez pas eu à cliquer sur un bloc qui recouvre la moitié de la page pour dire que vous êtes d’accord avec le dépôt de cookies.

- -

Rien d’exceptionnel, je respecte simplement la loi, qui dit que certains outils de suivi d’audience, correctement configurés pour respecter la vie privée, sont exemptés d’autorisation préalable.

- -

J’utilise pour cela Matomo, un outil libre, paramétré pour être en conformité avec la recommandation « Cookies » de la CNIL. Cela signifie que votre adresse IP, par exemple, est anonymisée avant d’être enregistrée. Il m’est donc impossible d’associer vos visites sur ce site à votre personne.

-

La lettre d'information et conformité RGPD

- -Ce site vous propose de vous inscrire à une lettre d'information. Pour ce faire, vous devez donner votre accord par deux fois : au moment de remplir le formulaire, et en cliquant sur un lien dans le mail de confirmation. - -Tous les emails qui vous sont envoyés dans le cadre de cette lettre d'information comportent un lien de désinscription. - -Votre adresse email est stockée en France chez Sendinblue, entreprise française. -
- - - -{% endblock %} diff --git a/datasette/templates/pages/versions.html b/datasette/templates/pages/versions.html deleted file mode 100644 index dc05133..0000000 --- a/datasette/templates/pages/versions.html +++ /dev/null @@ -1,98 +0,0 @@ -{% extends "base.html" %} -{% block title %}Notes de version{% endblock %} -{% block nav %} -

- accueil -

- {{ super() }} -{% endblock %} -{% block content %} - -
-

Notes de version

- - -

1.4.1 (14/06/2021)

- -
    -
  • ajout des traductions des opérations de filtrage à toutes les vues, pas seulement /db/decp
  • -
- -

1.4.0 (14/06/2021)

- -
    -
  • traduction des opérations de filtrage (ex : contains => contient)
  • - -
  • élargissement des menus de filtrage
  • - -
  • correction du titre de la page des notes de versions
  • -
- -

1.3.0 (03/06/2021)

- -
    -
  • utilisation de noms de colonnes plus lisibles dans l'application
  • - -
  • suppression des références à la licence et aux données source sur la page d'accueil
  • - -
  • correction des liens vers le code source
  • - -
  • correction de l'indentation des puces dans les notes de version
  • -
- - -

1.2.0 (28/05/2021)

- - - -

1.1.0 (25/05/2021)

- -
    -
  • ajout de nouvelles vues : - - -
      -
    • Marchés publics sans leurs titulaires : vue dédiée aux titulaires de marchés avec des données provenant du répertoire SIRENE
    • - -
    • Données sur les titulaires et géolocalisation : vue sans les titulaires pour analyser les nombres de marchés et les montants
    -
  • - -
  • amélioration de la page d'accueil
  • - -
  • développement de la page "db" avec description des vues et liste des colonnes
  • - -
  • les codes APE sont cliquables
  • - -
  • ajout des mentions légales
  • - -
  • ajout d'un formulatire d'inscription à une lettre d'information
  • - -
  • correction de bugs : - - -
      -
    • correction du format de certaines dates dans les données
    -
  • -
- -

1.0.0

- -
    -
  • publication sur https://decp.info
  • - -
  • ajout d'une vue équivalente au format DECP réglementaire
  • - -
  • personnalisation de datasette
  • - -
  • script de conversion quotidien basé sur dataflows
  • -
- -
- -{% endblock %} \ No newline at end of file diff --git a/datasette/templates/patterns.html b/datasette/templates/patterns.html deleted file mode 100644 index 3f9b5a1..0000000 --- a/datasette/templates/patterns.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - Datasette: Pattern Portfolio - - - - - - - -
- -
-

Pattern Portfolio

-
- - - - -

Header for /database/table/row and Messages

- -
- -
- -

Example message

-

Example message

-

Example message

- -

.bd for /

-
-

Datasette Fixtures

- -

- Data license: - Apache License 2.0 - · - Data source: - - tests/fixtures.py - · - About: - - About Datasette -

-

fixtures

-

- 1,258 rows in 24 tables, 206 rows in 5 hidden tables, 4 views -

-

compound_three_primary_keys, sortable, facetable, roadside_attraction_characteristics, simple_primary_key, ...

-

data

-

- 6 rows in 2 tables -

-

names, foo

-
- -

.bd for /database

-
- - - -

- Data license: - Apache License 2.0 - · - Data source: - - tests/fixtures.py - · - About: - - About Datasette -

-
-

Custom SQL query

-

-

- - -

-
-
-

123_starts_with_digits

-

content

-

0 rows

-
-
-

Table With Space In Name

-

pk, content

-

0 rows

-
-
-

attraction_characteristic

-

pk, name

-

2 rows

-
-
- -

.bd for /database/table

- -
- - -

- Data license: - Apache License 2.0 - · - Data source: - - tests/fixtures.py - · - About: - - About Datasette -

-

3 rows - where characteristic_id = 2 -

-
-
-
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
- - -
-
- -
-

2 extra where clauses

- -
- -

View and edit SQL

- - - -

- Suggested facets: tags, created (date), tags (array) -

- -
- -
-

- tags (array) - - - -

- -
- -
-

- created - - - -

- -
- -
-

- city_id - - - -

- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Link - - rowid ▼ - - attraction_id - - characteristic_id -
1The Mystery Spot 1Paranormal 2
2Winchester Mystery House 2Paranormal 2
3Bigfoot Discovery Museum 4Paranormal 2
-
-

Advanced export

-

JSON shape: - default, - array, - newline-delimited -

-
-

- CSV options: - - - - - -

-
-
-
CREATE TABLE roadside_attraction_characteristics (
-    attraction_id INTEGER REFERENCES roadside_attractions(pk),
-    characteristic_id INTEGER REFERENCES attraction_characteristic(pk)
-);
-
- -

.bd for /database/table/row

-
-

roadside_attractions: 2

-

This data as json

- - - - - - - - - - - - - - - - - - - -
- pk - - name - - address - - latitude - - longitude -
2Winchester Mystery House525 South Winchester Boulevard, San Jose, CA 9512837.3184-121.9511
-

Links from other tables

-
    -
  • - - 1 row - from attraction_id in roadside_attraction_characteristics -
  • -
-
- -

.ft

- - - -{% include "_close_open_menus.html" %} - - - diff --git a/datasette/templates/permissions_debug.html b/datasette/templates/permissions_debug.html deleted file mode 100644 index d898ea8..0000000 --- a/datasette/templates/permissions_debug.html +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Debug permissions{% endblock %} - -{% block extra_head %} - -{% endblock %} - -{% block nav %} -

- home -

- {{ super() }} -{% endblock %} - -{% block content %} - -

Recent permissions checks

- -{% for check in permission_checks %} -
-

- {{ check.action }} - checked at - {{ check.when }} - {% if check.result %} - - {% else %} - - {% endif %} - {% if check.used_default %} - (used default) - {% endif %} -

-

Actor: {{ check.actor|tojson }}

- {% if check.resource %} -

Resource: {{ check.resource }}

- {% endif %} -
-{% endfor %} - -{% endblock %} diff --git a/datasette/templates/query.html b/datasette/templates/query.html deleted file mode 100644 index 9b3fff2..0000000 --- a/datasette/templates/query.html +++ /dev/null @@ -1,87 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ database }}{% if query and query.sql %}: {{ query.sql }}{% endif %}{% endblock %} - -{% block extra_head %} -{{ super() }} -{% if columns %} - -{% endif %} -{% include "_codemirror.html" %} -{% endblock %} - -{% block body_class %}query db-{{ database|to_css_class }}{% if canned_query %} query-{{ canned_query|to_css_class }}{% endif %}{% endblock %} - -{% block nav %} -

- home / - {{ database }} -

- {{ super() }} -{% endblock %} - -{% block content %} - -

{{ metadata.title or database }}{% if canned_query and not metadata.title %}: {{ canned_query }}{% endif %}{% if private %} 🔒{% endif %}

- -{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %} - -
-

Custom SQL query{% if display_rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(display_rows|length) }} row{% if display_rows|length == 1 %}{% else %}s{% endif %}{% endif %} {% if hide_sql %}(show){% else %}(hide){% endif %}

- {% if not hide_sql %} - {% if editable and allow_execute_sql %} -

- {% else %} -
{% if query %}{{ query.sql }}{% endif %}
- {% endif %} - {% else %} - - - {% endif %} - {% if named_parameter_values %} -

Query parameters

- {% for name, value in named_parameter_values.items() %} -

- {% endfor %} - {% endif %} -

- - {% if canned_write %}{% endif %} - - {% if canned_query and edit_sql_url %}Edit SQL{% endif %} -

-
- -{% if display_rows %} - -
- - - {% for column in columns %}{% endfor %} - - - - {% for row in display_rows %} - - {% for column, td in zip(columns, row) %} - - {% endfor %} - - {% endfor %} - -
{{ column }}
{{ td }}
-{% else %} - {% if not canned_write %} -

0 results

- {% endif %} -{% endif %} - -{% include "_codemirror_foot.html" %} - -{% endblock %} diff --git a/datasette/templates/row.html b/datasette/templates/row.html deleted file mode 100644 index 5823110..0000000 --- a/datasette/templates/row.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ database }}: {{ table }}{% endblock %} - -{% block extra_head %} -{{ super() }} - -{% endblock %} - -{% block body_class %}row db-{{ database|to_css_class }} table-{{ table|to_css_class }}{% endblock %} - -{% block nav %} -

- accueil / - {{ database }} / - {{ table }} -

- {{ super() }} -{% endblock %} - -{% block content %} -

{{ table }}: {{ ', '.join(primary_key_values) }}

- -{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %} - -

Télcharger ces données au format {% for name, url in renderers.items() %}{{ name }}{{ ", " if not loop.last }}{% endfor %}

- -{% include custom_table_templates %} - -{% if foreign_key_tables %} -

Liens depuis d'autres tables

- -{% endif %} - -{% endblock %} diff --git a/datasette/templates/show_json.html b/datasette/templates/show_json.html deleted file mode 100644 index fd88756..0000000 --- a/datasette/templates/show_json.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ filename }}{% endblock %} - -{% block body_class %}show-json{% endblock %} - -{% block nav %} -

- home -

- {{ super() }} -{% endblock %} - -{% block content %} -

{{ filename }}

- -
{{ data_json }}
- -{% endblock %} diff --git a/datasette/templates/table.html b/datasette/templates/table.html deleted file mode 100644 index a4a1fae..0000000 --- a/datasette/templates/table.html +++ /dev/null @@ -1,221 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ database }}: {{ table }}: {% if filtered_table_rows_count or filtered_table_rows_count == 0 %}{{ "{:,}".format(filtered_table_rows_count) }} ligne{% if filtered_table_rows_count == 1 %}{% else %}s{% endif %}{% endif %} - {% if human_description_en %}où {{ human_description_en }}{% endif %}{% endblock %} - -{% block extra_head %} -{{ super() }} - - -{% endblock %} - - -{% block body_class %}table db-{{ database|to_css_class }} table-{{ table|to_css_class }}{% endblock %} - -{% block nav %} -

- accueil / - {{ database }} -

- {{ super() }} -{% endblock %} - -{% block content %} - - -{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %} - -{% if filtered_table_rows_count or human_description_en %} -

{% if filtered_table_rows_count or filtered_table_rows_count == 0 %}{{ "{:,}".format(filtered_table_rows_count) }} ligne{% if filtered_table_rows_count == 1 %}{% else %}s{% endif %}{% endif %} - -

-{% endif %} - -
- {% if supports_search %} -
- {% endif %} - {% for column, lookup, value in filters.selections() %} -
-
- -
- -
-
- {% endfor %} -
-
- -
- -
-
-
- {% if is_sortable %} -
- -
- - {% endif %} - {% for key, value in form_hidden_args %} - - {% endfor %} - -
-
- -{% if extra_wheres_for_ui %} -
-

{{ extra_wheres_for_ui|length }} extra where clause{% if extra_wheres_for_ui|length != 1 %}s{% endif %}

-
    - {% for extra_where in extra_wheres_for_ui %} -
  • {{ extra_where.text }} [supprimer]
  • - {% endfor %} -
-
-{% endif %} - - - - - - - -{% include custom_table_templates %} - -{% if next_url %} -

Page suivante

-{% endif %} - - - - - -{% endblock %} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..86fb930 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[project] +name = "decp.info" +description = "" +version = "2.0.0" +requires-python = ">= 3.10" +authors = [ + { name = "Colin Maudry", email = "colin+decp@maudry.com" } +] +dependencies = [ + "dash", + "polars" +] + +[project.optional-dependencies] +dev = [ + "pre-commit", +] diff --git a/scripts/start-datasette.sh b/scripts/start-datasette.sh deleted file mode 100755 index 49b8d54..0000000 --- a/scripts/start-datasette.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -echo "Getting data from data.gouv.fr..." -wget -nv https://www.data.gouv.fr/fr/datasets/r/c6b08d03-7aa4-4132-b5b2-fd76633feecc -O datasette/db.db - -datasette inspect datasette/*.db --inspect-file=datasette/inspect-data.json - -echo "Starting datasette..." -datasette datasette/ --port 9090 --cors | grep -v "/static/" diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..5f77277 --- /dev/null +++ b/src/app.py @@ -0,0 +1,40 @@ +from dash import Dash, html, dcc, callback, Output, Input, dash_table +import plotly.express as px +import polars as pl + +df = pl.read_parquet( + "https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432" +) + +app = Dash() + +app.layout = [ + html.H1(children="decp.info", style={"textAlign": "center"}), + dash_table.DataTable( + id="table", + data=df.to_dicts(), + page_size=20, + page_current=0, + page_action="native", + filter_action="native", + columns=[ + {"name": i, "id": i, "deletable": True, "selectable": True} + for i in df.columns + ], + selected_columns=[], + selected_rows=[], + sort_action="native", + sort_mode="multi", + ), +] + + +@callback( + Output("table", "data"), Input("table", "page_current"), Input("table", "page_size") +) +def update_table(page_current, page_size): + return df[page_current * page_size : (page_current + 1) * page_size].to_dicts() + + +if __name__ == "__main__": + app.run(debug=True) From 2b17f64904efb34329fc6f701288597321baa173 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Sun, 20 Apr 2025 23:33:12 +0200 Subject: [PATCH 02/19] Execution en serveur gunicorn --- README.md | 2 +- src/app.py => app.py | 25 +++++++++++++++++++++---- pyproject.toml | 3 ++- 3 files changed, 24 insertions(+), 6 deletions(-) rename src/app.py => app.py (58%) diff --git a/README.md b/README.md index 02ee76e..ba10c99 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Outil d'exploration et de téléchargement des données essentielles de la comma python -m venv .venv source .venv/bin/activate pip install . -python src/app.py +gunicorn app:server ``` ## Dépôts de code connexes diff --git a/src/app.py b/app.py similarity index 58% rename from src/app.py rename to app.py index 5f77277..ebe018f 100644 --- a/src/app.py +++ b/app.py @@ -1,14 +1,20 @@ from dash import Dash, html, dcc, callback, Output, Input, dash_table import plotly.express as px import polars as pl +import dash_bootstrap_components as dbc -df = pl.read_parquet( - "https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432" -) +df = pl.read_ipc("/home/colin/git/decp-processing/dist/decp.arrow") -app = Dash() +app = Dash(external_stylesheets=[dbc.themes.UNITED]) +server = app.server app.layout = [ + html.Div( + [ + "Recherche (acheteur, titulaire, objet) : ", + dcc.Input(id="search", value="", type="text"), + ] + ), html.H1(children="decp.info", style={"textAlign": "center"}), dash_table.DataTable( id="table", @@ -29,6 +35,17 @@ app.layout = [ ] +@callback( + Output(component_id="table", component_property="data", allow_duplicate=True), + Input(component_id="search", component_property="value"), + prevent_initial_call=True, +) +def global_search(text): + new_df = df + new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text)) + return new_df.to_dicts() + + @callback( Output("table", "data"), Input("table", "page_current"), Input("table", "page_size") ) diff --git a/pyproject.toml b/pyproject.toml index 86fb930..0640f72 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,8 @@ authors = [ ] dependencies = [ "dash", - "polars" + "polars", + "gunicorn" ] [project.optional-dependencies] From 8b389515c4588976e3a0f7e7612c043ee2190e11 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 00:09:30 +0200 Subject: [PATCH 03/19] Parquet dgfr url --- app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.py b/app.py index ebe018f..647a386 100644 --- a/app.py +++ b/app.py @@ -3,7 +3,9 @@ import plotly.express as px import polars as pl import dash_bootstrap_components as dbc -df = pl.read_ipc("/home/colin/git/decp-processing/dist/decp.arrow") +df = pl.read_parquet( + "https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432" +) app = Dash(external_stylesheets=[dbc.themes.UNITED]) server = app.server From ddcb8df904790d8e728de9e666964953753ef6b5 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 00:19:44 +0200 Subject: [PATCH 04/19] Removed unused import, add dcc dependency --- app.py | 1 - pyproject.toml | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index 647a386..f5ca7a2 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,4 @@ from dash import Dash, html, dcc, callback, Output, Input, dash_table -import plotly.express as px import polars as pl import dash_bootstrap_components as dbc diff --git a/pyproject.toml b/pyproject.toml index 0640f72..5f52b1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,8 @@ authors = [ dependencies = [ "dash", "polars", - "gunicorn" + "gunicorn", + "dash-bootstrap-components" ] [project.optional-dependencies] From 2687705f29e594e300ee9afe97e20d800b4985cb Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 01:01:13 +0200 Subject: [PATCH 05/19] Ajout d'un spinner de chargement --- app.py | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/app.py b/app.py index f5ca7a2..3def853 100644 --- a/app.py +++ b/app.py @@ -6,32 +6,38 @@ df = pl.read_parquet( "https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432" ) -app = Dash(external_stylesheets=[dbc.themes.UNITED]) +app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info") server = app.server +datatable = dash_table.DataTable( + id="table", + data=df.to_dicts(), + page_size=20, + page_current=0, + page_action="native", + # filter_action="native", + columns=[ + {"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns + ], + selected_columns=[], + selected_rows=[], + sort_action="native", + sort_mode="multi", +) + app.layout = [ + html.H1(children="decp.info", style={"textAlign": "center"}), html.Div( [ - "Recherche (acheteur, titulaire, objet) : ", + "Recherche dans objet : ", dcc.Input(id="search", value="", type="text"), ] ), - html.H1(children="decp.info", style={"textAlign": "center"}), - dash_table.DataTable( - id="table", - data=df.to_dicts(), - page_size=20, - page_current=0, - page_action="native", - filter_action="native", - columns=[ - {"name": i, "id": i, "deletable": True, "selectable": True} - for i in df.columns - ], - selected_columns=[], - selected_rows=[], - sort_action="native", - sort_mode="multi", + dcc.Loading( + overlay_style={"visibility": "visible", "filter": "blur(2px)"}, + id="loading-1", + type="default", + children=datatable, ), ] From fd0dc4643d5e15cb4825a078de982600b927ca16 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 01:06:19 +0200 Subject: [PATCH 06/19] gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 205fb09..48dbfa9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.db -.egg-info +*.egg-info +__pycache__ +.idea From 55dca61a96467e9a325530d4837faa8e4482c72f Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 01:19:04 +0200 Subject: [PATCH 07/19] =?UTF-8?q?Pas=20de=20s=C3=A9lection=20colonne/cellu?= =?UTF-8?q?e,=20fixed=20pagination?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index 3def853..7f81984 100644 --- a/app.py +++ b/app.py @@ -10,6 +10,7 @@ app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info") server = app.server datatable = dash_table.DataTable( + cell_selectable=False, id="table", data=df.to_dicts(), page_size=20, @@ -17,7 +18,7 @@ datatable = dash_table.DataTable( page_action="native", # filter_action="native", columns=[ - {"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns + {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns ], selected_columns=[], selected_rows=[], @@ -53,11 +54,11 @@ def global_search(text): return new_df.to_dicts() -@callback( - Output("table", "data"), Input("table", "page_current"), Input("table", "page_size") -) -def update_table(page_current, page_size): - return df[page_current * page_size : (page_current + 1) * page_size].to_dicts() +# @callback( +# Output("table", "data"), Input("table", "page_current"), Input("table", "page_size") +# ) +# def update_table(page_current, page_size): +# return df[page_current * page_size : (page_current + 1) * page_size].to_dicts() if __name__ == "__main__": From 34c129bd18cba43ff65ec2537254ffbe81abd63c Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 12:39:20 +0200 Subject: [PATCH 08/19] Ajout du bouton Export (XLSX), les filtres natifs fonctionnent --- .gitignore | 1 + app.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 48dbfa9..f96ed0a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.egg-info __pycache__ .idea +.venv diff --git a/app.py b/app.py index 7f81984..60e80bc 100644 --- a/app.py +++ b/app.py @@ -16,7 +16,8 @@ datatable = dash_table.DataTable( page_size=20, page_current=0, page_action="native", - # filter_action="native", + filter_action="native", + filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, columns=[ {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns ], @@ -24,6 +25,9 @@ datatable = dash_table.DataTable( selected_rows=[], sort_action="native", sort_mode="multi", + export_format="xlsx", + export_columns="visible", + export_headers="ids", ) app.layout = [ From 918236212ca00a492177afa08fc8506cff9224aa Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 13:38:37 +0200 Subject: [PATCH 09/19] =?UTF-8?q?D=C3=A9placement=20de=20app=20dans=20src,?= =?UTF-8?q?=20cr=C3=A9ation=20de=20run.py,=20ajout=20de=20prettier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 5 +++++ run.py | 9 +++++++++ src/__init__.py | 0 app.py => src/app.py | 18 +++++++++++++++--- 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 run.py create mode 100644 src/__init__.py rename app.py => src/app.py (73%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2763415..bd6e4d4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,3 +17,8 @@ repos: hooks: - id: black-jupyter args: [ --config=pyproject.toml ] + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.5.1 + hooks: + - id: prettier + files: \.(js|css|html|json|md)$ diff --git a/run.py b/run.py new file mode 100644 index 0000000..115f3b7 --- /dev/null +++ b/run.py @@ -0,0 +1,9 @@ +from os import getenv +from src.app import app + +# To use `gunicorn run:server` (prod) +server = app.server + +# To use `python index.py` (dev) +if __name__ == "__main__": + app.run(debug=True) diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app.py b/src/app.py similarity index 73% rename from app.py rename to src/app.py index 60e80bc..21d54ac 100644 --- a/app.py +++ b/src/app.py @@ -2,9 +2,7 @@ from dash import Dash, html, dcc, callback, Output, Input, dash_table import polars as pl import dash_bootstrap_components as dbc -df = pl.read_parquet( - "https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432" -) +df = pl.read_parquet("/home/colin/git/decp-processing/dist/2025-04-21/decp.parquet") app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info") server = app.server @@ -32,6 +30,20 @@ datatable = dash_table.DataTable( app.layout = [ html.H1(children="decp.info", style={"textAlign": "center"}), + html.Details( + children=[ + html.Summary("Utilisation"), + dcc.Markdown( + """ + Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`. + + - Champs textuels : la recherche est insensible à la casse (majuscules/minuscules). + - Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur. + """ + ), + ], + id="instructions", + ), html.Div( [ "Recherche dans objet : ", From 578041cb7f553144de1a5b450750b319c5616b2b Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 13:54:40 +0200 Subject: [PATCH 10/19] ajout d'aide pour les filtres, personnalisation du bouton Export close #6 --- src/app.py | 11 +++++++++++ src/assets/style.css | 13 +++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/assets/style.css diff --git a/src/app.py b/src/app.py index 21d54ac..b53350c 100644 --- a/src/app.py +++ b/src/app.py @@ -35,10 +35,21 @@ app.layout = [ html.Summary("Utilisation"), dcc.Markdown( """ + + **Filtres** + Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`. - Champs textuels : la recherche est insensible à la casse (majuscules/minuscules). - Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur. + + **Télécharger le résultat** + + Vous pouvez télécharger le résultat de vos filtres et tris en cliquant sur Télécharger au format Excel. + + Les colonnes supprimées seront absentes du fichier téléchargé. + + Si vous téléchargez un volume important de données, il se peut que vous attendiez quelques minutes avant le début du téléchargement. """ ), ], diff --git a/src/assets/style.css b/src/assets/style.css new file mode 100644 index 0000000..435c5b3 --- /dev/null +++ b/src/assets/style.css @@ -0,0 +1,13 @@ +/* Change le texte du bout d'export */ +button.export { + font-size: 0; +} +button.export:before { + content: "Télécharger au format Excel"; + font-size: 14px; +} + +/* Masquer le bouton de configuration de la casse dans les filtres */ +input.dash-filter--case { + display: none; +} From 75e09b0bc68a9a079d23537f3a3c413697a6bddc Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 14:32:01 +0200 Subject: [PATCH 11/19] =?UTF-8?q?R=C3=A9glage=20de=20la=20taille=20du=20te?= =?UTF-8?q?xte=20colonne=20objet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.py | 12 +++++++++++- src/assets/style.css | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/app.py b/src/app.py index b53350c..f832877 100644 --- a/src/app.py +++ b/src/app.py @@ -26,10 +26,20 @@ datatable = dash_table.DataTable( export_format="xlsx", export_columns="visible", export_headers="ids", + style_cell_conditional=[ + { + "if": {"column_id": "objet"}, + "minWidth": "300px", + "textAlign": "left", + "overflow": "hidden", + "lineHeight": "14px", + "whiteSpace": "normal", + }, + ], ) app.layout = [ - html.H1(children="decp.info", style={"textAlign": "center"}), + html.H1(children="decp.info"), html.Details( children=[ html.Summary("Utilisation"), diff --git a/src/assets/style.css b/src/assets/style.css index 435c5b3..dcd8cf0 100644 --- a/src/assets/style.css +++ b/src/assets/style.css @@ -11,3 +11,9 @@ button.export:before { input.dash-filter--case { display: none; } + +/* Réduire la taille du texte de la colonne Objet */ + +td[data-dash-column="objet"] { + font-size: 85%; +} From 60d204b061b496fd4bdf83e0daff7762392317a2 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 18:09:10 +0200 Subject: [PATCH 12/19] Ajout d'un menu de navigation --- pyproject.toml | 3 +- src/app.py | 104 ++++++++-------------------------------- src/assets/style.css | 41 ++++++++++++++++ src/pages/about.py | 9 ++++ src/pages/home.py | 95 ++++++++++++++++++++++++++++++++++++ src/pages/statistics.py | 9 ++++ 6 files changed, 175 insertions(+), 86 deletions(-) create mode 100644 src/pages/about.py create mode 100644 src/pages/home.py create mode 100644 src/pages/statistics.py diff --git a/pyproject.toml b/pyproject.toml index 5f52b1a..ba2a73c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,8 @@ dependencies = [ "dash", "polars", "gunicorn", - "dash-bootstrap-components" + "dash-bootstrap-components", + "python-dotenv" ] [project.optional-dependencies] diff --git a/src/app.py b/src/app.py index f832877..f97ff3f 100644 --- a/src/app.py +++ b/src/app.py @@ -1,101 +1,35 @@ -from dash import Dash, html, dcc, callback, Output, Input, dash_table -import polars as pl +from dash import Dash, html, page_container, page_registry, dcc import dash_bootstrap_components as dbc -df = pl.read_parquet("/home/colin/git/decp-processing/dist/2025-04-21/decp.parquet") - -app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info") +app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info", use_pages=True) server = app.server -datatable = dash_table.DataTable( - cell_selectable=False, - id="table", - data=df.to_dicts(), - page_size=20, - page_current=0, - page_action="native", - filter_action="native", - filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, - columns=[ - {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns - ], - selected_columns=[], - selected_rows=[], - sort_action="native", - sort_mode="multi", - export_format="xlsx", - export_columns="visible", - export_headers="ids", - style_cell_conditional=[ - { - "if": {"column_id": "objet"}, - "minWidth": "300px", - "textAlign": "left", - "overflow": "hidden", - "lineHeight": "14px", - "whiteSpace": "normal", - }, - ], -) - app.layout = [ - html.H1(children="decp.info"), - html.Details( - children=[ - html.Summary("Utilisation"), - dcc.Markdown( - """ - - **Filtres** - - Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`. - - - Champs textuels : la recherche est insensible à la casse (majuscules/minuscules). - - Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur. - - **Télécharger le résultat** - - Vous pouvez télécharger le résultat de vos filtres et tris en cliquant sur Télécharger au format Excel. - - Les colonnes supprimées seront absentes du fichier téléchargé. - - Si vous téléchargez un volume important de données, il se peut que vous attendiez quelques minutes avant le début du téléchargement. - """ - ), - ], - id="instructions", - ), html.Div( [ - "Recherche dans objet : ", - dcc.Input(id="search", value="", type="text"), - ] - ), - dcc.Loading( - overlay_style={"visibility": "visible", "filter": "blur(2px)"}, - id="loading-1", - type="default", - children=datatable, + html.H1("decp.info"), + html.Div( + [ + dcc.Link(page["name"], href=page["relative_path"], className="nav") + for page in page_registry.values() + ] + ), + ], + className="navbar", ), + page_container, ] -@callback( - Output(component_id="table", component_property="data", allow_duplicate=True), - Input(component_id="search", component_property="value"), - prevent_initial_call=True, -) -def global_search(text): - new_df = df - new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text)) - return new_df.to_dicts() - - # @callback( -# Output("table", "data"), Input("table", "page_current"), Input("table", "page_size") +# Output(component_id="table", component_property="data", allow_duplicate=True), +# Input(component_id="search", component_property="value"), +# prevent_initial_call=True, # ) -# def update_table(page_current, page_size): -# return df[page_current * page_size : (page_current + 1) * page_size].to_dicts() +# def global_search(text): +# new_df = df +# new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text)) +# return new_df.to_dicts() if __name__ == "__main__": diff --git a/src/assets/style.css b/src/assets/style.css index dcd8cf0..aed2e2e 100644 --- a/src/assets/style.css +++ b/src/assets/style.css @@ -17,3 +17,44 @@ input.dash-filter--case { td[data-dash-column="objet"] { font-size: 85%; } + +.dash-table-container + .dash-spreadsheet-container + .dash-spreadsheet-inner + th.dash-header { + background-color: #666986; + color: white; +} + +.dash-table-container + .dash-spreadsheet-container + .dash-spreadsheet-inner + th.dash-filter { + background-color: #d0d2e6; +} + +#header > *, +.dash-spreadsheet-menu button.export { + margin: 0 0 20px 20px; +} + +.navbar { + width: 100%; + height: 100px; + padding: 10px; +} + +a.nav { + float: left; + margin-right: 40px; + font-size: 120%; +} + +h1 { + float: left; + width: 50%; +} + +h3 { + display: inline; +} diff --git a/src/pages/about.py b/src/pages/about.py new file mode 100644 index 0000000..6118c1c --- /dev/null +++ b/src/pages/about.py @@ -0,0 +1,9 @@ +from dash import register_page, html, page_registry + +title = "À propos" + +register_page( + __name__, path="/a-propos", title=f"decp.info - {title}", name=title, order=3 +) + +layout = [html.H2(title)] diff --git a/src/pages/home.py b/src/pages/home.py new file mode 100644 index 0000000..8e54855 --- /dev/null +++ b/src/pages/home.py @@ -0,0 +1,95 @@ +from dash import ( + Dash, + html, + dcc, + callback, + Output, + Input, + dash_table, + page_container, + register_page, +) +from dotenv import load_dotenv +import os +import polars as pl + +load_dotenv() + +df = pl.read_parquet(os.getenv("DATA_FILE_PARQUET_PATH")) + +title = "Tableau" +register_page(__name__, path="/", title=f"decp.info - {title}", name=title, order=1) + +datatable = dash_table.DataTable( + cell_selectable=False, + id="table", + data=df.to_dicts(), + page_size=20, + page_current=0, + page_action="native", + filter_action="native", + filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, + columns=[ + {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns + ], + selected_columns=[], + selected_rows=[], + sort_action="native", + sort_mode="multi", + export_format="xlsx", + export_columns="visible", + export_headers="ids", + style_cell_conditional=[ + { + "if": {"column_id": "objet"}, + "minWidth": "300px", + "textAlign": "left", + "overflow": "hidden", + "lineHeight": "14px", + "whiteSpace": "normal", + }, + ], +) + +layout = [ + html.Div( + html.Details( + children=[ + html.Summary(html.H3("Utilisation")), + dcc.Markdown( + """ + + **Filtres** + + Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`. + + - Champs textuels : la recherche est insensible à la casse (majuscules/minuscules). + - Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur. + + **Télécharger le résultat** + + Vous pouvez télécharger le résultat de vos filtres et tris en cliquant sur Télécharger au format Excel. + + Les colonnes supprimées seront absentes du fichier téléchargé. + + Si vous téléchargez un volume important de données, il se peut que vous attendiez quelques minutes avant le début du téléchargement. + """ + ), + ], + id="instructions", + ), + id="header", + ), + # html.Div( + # [ + # "Recherche dans objet : ", + # dcc.Input(id="search", value="", type="text"), + # ] + # )]), + dcc.Loading( + overlay_style={"visibility": "visible", "filter": "blur(2px)"}, + id="loading-1", + type="default", + children=datatable, + ), +] diff --git a/src/pages/statistics.py b/src/pages/statistics.py new file mode 100644 index 0000000..ad297d6 --- /dev/null +++ b/src/pages/statistics.py @@ -0,0 +1,9 @@ +from dash import register_page, html + +title = "Statistiques" + +register_page( + __name__, path="/statistiques", title=f"decp.info - {title}", name=title, order=2 +) + +layout = [html.H2(title)] From 7082041853b222fec6513372a9f7e989ee8f3e20 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 18:16:45 +0200 Subject: [PATCH 13/19] Nettoyage des imports --- .gitignore | 2 ++ .template.env | 3 +++ src/pages/about.py | 2 +- src/pages/home.py | 5 ----- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 .template.env diff --git a/.gitignore b/.gitignore index f96ed0a..ff28d7e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ __pycache__ .idea .venv +build +.env diff --git a/.template.env b/.template.env new file mode 100644 index 0000000..5cbcdfa --- /dev/null +++ b/.template.env @@ -0,0 +1,3 @@ +DATA_FILE_PARQUET_PATH=https://www.data.gouv.fr/fr/datasets/r/11cea8e8-df3e-4ed1-932b-781e2635e432 +PORT=8050 +DEVELOPMENT=True diff --git a/src/pages/about.py b/src/pages/about.py index 6118c1c..0eb04f4 100644 --- a/src/pages/about.py +++ b/src/pages/about.py @@ -1,4 +1,4 @@ -from dash import register_page, html, page_registry +from dash import register_page, html title = "À propos" diff --git a/src/pages/home.py b/src/pages/home.py index 8e54855..8fe98fa 100644 --- a/src/pages/home.py +++ b/src/pages/home.py @@ -1,12 +1,7 @@ from dash import ( - Dash, html, dcc, - callback, - Output, - Input, dash_table, - page_container, register_page, ) from dotenv import load_dotenv From c8cae37ff190d15681cde24dbaa18fa1045dabb2 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 18:34:42 +0200 Subject: [PATCH 14/19] Suppression de la navbar en attendant d'avoir plus de contenu --- pyproject.toml | 2 +- src/app.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ba2a73c..835bb7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "polars", "gunicorn", "dash-bootstrap-components", - "python-dotenv" + "python-dotenv", ] [project.optional-dependencies] diff --git a/src/app.py b/src/app.py index f97ff3f..e4e47cb 100644 --- a/src/app.py +++ b/src/app.py @@ -1,19 +1,21 @@ from dash import Dash, html, page_container, page_registry, dcc import dash_bootstrap_components as dbc + app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info", use_pages=True) server = app.server + app.layout = [ html.Div( [ html.H1("decp.info"), - html.Div( - [ - dcc.Link(page["name"], href=page["relative_path"], className="nav") - for page in page_registry.values() - ] - ), + # html.Div( + # [ + # dcc.Link(page["name"], href=page["relative_path"], className="nav") + # for page in page_registry.values() + # ] + # ), ], className="navbar", ), From 67ee8628da97e4bd0d2039ad3677d3f221fbc80a Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 19:12:43 +0200 Subject: [PATCH 15/19] =?UTF-8?q?Avec=20gunicorn=20le=20page=5Fcontainer?= =?UTF-8?q?=20=C3=A9tait=20introuvable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 4 ++-- src/app.py | 38 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/run.py b/run.py index 115f3b7..435d1e9 100644 --- a/run.py +++ b/run.py @@ -4,6 +4,6 @@ from src.app import app # To use `gunicorn run:server` (prod) server = app.server -# To use `python index.py` (dev) +# To use `python run.py` (dev) if __name__ == "__main__": - app.run(debug=True) + app.run_server(debug=True) diff --git a/src/app.py b/src/app.py index e4e47cb..a88fc54 100644 --- a/src/app.py +++ b/src/app.py @@ -3,26 +3,27 @@ import dash_bootstrap_components as dbc app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info", use_pages=True) -server = app.server - - -app.layout = [ - html.Div( - [ - html.H1("decp.info"), - # html.Div( - # [ - # dcc.Link(page["name"], href=page["relative_path"], className="nav") - # for page in page_registry.values() - # ] - # ), - ], - className="navbar", - ), - page_container, -] +app.layout = html.Div( + [ + html.Div( + [ + html.H1("decp.info"), + html.Div( + [ + dcc.Link( + page["name"], href=page["relative_path"], className="nav" + ) + for page in page_registry.values() + ] + ), + ], + className="navbar", + ), + page_container, + ] +) # @callback( # Output(component_id="table", component_property="data", allow_duplicate=True), # Input(component_id="search", component_property="value"), @@ -33,6 +34,5 @@ app.layout = [ # new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text)) # return new_df.to_dicts() - if __name__ == "__main__": app.run(debug=True) From 3b1f3c8c65badbe15fbd694530b21539b48ff221 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 23:03:02 +0200 Subject: [PATCH 16/19] Code custom pour la pagination et les filtres avec chunking #7 --- src/pages/__init__.py | 0 src/pages/home.py | 70 +++++++++++++++++++++++++++++++++++-------- src/utils.py | 19 ++++++++++++ 3 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 src/pages/__init__.py create mode 100644 src/utils.py diff --git a/src/pages/__init__.py b/src/pages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/home.py b/src/pages/home.py index 8fe98fa..ee49545 100644 --- a/src/pages/home.py +++ b/src/pages/home.py @@ -1,16 +1,12 @@ -from dash import ( - html, - dcc, - dash_table, - register_page, -) +from dash import html, dcc, dash_table, register_page, Input, Output, State, callback from dotenv import load_dotenv import os import polars as pl +from src.utils import split_filter_part load_dotenv() -df = pl.read_parquet(os.getenv("DATA_FILE_PARQUET_PATH")) +df = pl.scan_parquet(os.getenv("DATA_FILE_PARQUET_PATH")) title = "Tableau" register_page(__name__, path="/", title=f"decp.info - {title}", name=title, order=1) @@ -18,19 +14,18 @@ register_page(__name__, path="/", title=f"decp.info - {title}", name=title, orde datatable = dash_table.DataTable( cell_selectable=False, id="table", - data=df.to_dicts(), page_size=20, page_current=0, - page_action="native", - filter_action="native", - filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, + page_action="custom", + filter_action="custom", + # filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, columns=[ {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns ], selected_columns=[], selected_rows=[], - sort_action="native", - sort_mode="multi", + # sort_action="native", + # sort_mode="multi", export_format="xlsx", export_columns="visible", export_headers="ids", @@ -44,6 +39,7 @@ datatable = dash_table.DataTable( "whiteSpace": "normal", }, ], + data_timestamp=0, ) layout = [ @@ -88,3 +84,51 @@ layout = [ children=datatable, ), ] + + +@callback( + Output("table", "data"), + Output("table", "data_timestamp"), + Input("table", "page_current"), + Input("table", "page_size"), + Input("table", "filter_query"), + State("table", "data_timestamp"), +) +def update_table(page_current, page_size, filter_query, data_timestamp): + print(" + + + + + + + + + + + + + + + + + + ") + print("Filter query:", filter_query) + # 1. Apply Filters + dff = df # start from the original data + if filter_query: + filtering_expressions = filter_query.split(" && ") + for filter_part in filtering_expressions: + col_name, operator, filter_value = split_filter_part(filter_part) + print("filter_value:", filter_value) + print("filter_value_type:", type(filter_value)) + + if operator in ("<", "<=", ">", ">="): + filter_value = int(filter_value) + if operator == "<": + dff = dff.filter(pl.col(col_name) < filter_value) + elif operator == ">": + dff = dff.filter(pl.col(col_name) > filter_value) + elif operator == ">=": + dff = dff.filter(pl.col(col_name) >= filter_value) + elif operator == "<=": + dff = dff.filter(pl.col(col_name) <= filter_value) + # these operators match polars series filter operators + + elif operator == "contains": + dff = dff.filter(pl.col(col_name).str.contains("(?i)" + filter_value)) + # elif operator == 'datestartswith': + # dff = dff.filter(pl.col(col_name).str.startswith(filter_value)") + + # 2. Paginate Data + start_row = page_current * page_size + # end_row = (page_current + 1) * page_size + + dff = dff.slice(start_row, page_size).collect() + # print("dff_sliced:", dff.select("titulaire.typeId")) + dff = dff.to_dicts() + + return dff, data_timestamp + 1 # update data, update timestamp diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..cb47448 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,19 @@ +operators = [ + ["s<", "<"], + ["s>", ">"], + ["scontains", "contains"], +] + + +def split_filter_part(filter_part): + print("filter part", filter_part) + for operator_group in operators: + if operator_group[0] in filter_part: + name_part, value_part = filter_part.split(operator_group[0], 1) + name_part = name_part.strip() + value = value_part.strip() + name = name_part[name_part.find("{") + 1 : name_part.rfind("}")] + + return name, operator_group[1], value + + return [None] * 3 From 5563ff49f8d5631ba46d5e1ff8d55a5e2b700282 Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Mon, 21 Apr 2025 23:43:29 +0200 Subject: [PATCH 17/19] Couleurs chaudes, placeholder pour les filtres --- run.py | 2 +- src/assets/style.css | 8 ++++++-- src/pages/home.py | 8 +++----- src/utils.py | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/run.py b/run.py index 435d1e9..0c750a9 100644 --- a/run.py +++ b/run.py @@ -6,4 +6,4 @@ server = app.server # To use `python run.py` (dev) if __name__ == "__main__": - app.run_server(debug=True) + app.run(debug=True) diff --git a/src/assets/style.css b/src/assets/style.css index aed2e2e..bedd3c8 100644 --- a/src/assets/style.css +++ b/src/assets/style.css @@ -22,7 +22,7 @@ td[data-dash-column="objet"] { .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-header { - background-color: #666986; + background-color: #b33821; color: white; } @@ -30,7 +30,11 @@ td[data-dash-column="objet"] { .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-filter { - background-color: #d0d2e6; + background-color: #f0afa3; +} + +#table tr:nth-child(even) td { + background-color: #feeeee; } #header > *, diff --git a/src/pages/home.py b/src/pages/home.py index ee49545..3fba171 100644 --- a/src/pages/home.py +++ b/src/pages/home.py @@ -18,10 +18,8 @@ datatable = dash_table.DataTable( page_current=0, page_action="custom", filter_action="custom", - # filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, - columns=[ - {"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns - ], + filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."}, + columns=[{"name": i, "id": i} for i in df.collect_schema().names()], selected_columns=[], selected_rows=[], # sort_action="native", @@ -32,7 +30,7 @@ datatable = dash_table.DataTable( style_cell_conditional=[ { "if": {"column_id": "objet"}, - "minWidth": "300px", + "minWidth": "350px", "textAlign": "left", "overflow": "hidden", "lineHeight": "14px", diff --git a/src/utils.py b/src/utils.py index cb47448..d422ada 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,7 +1,7 @@ operators = [ ["s<", "<"], ["s>", ">"], - ["scontains", "contains"], + ["icontains", "contains"], ] From e4a670948de07437cd6987d1aedce3599055e30b Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Fri, 30 May 2025 21:38:14 +0200 Subject: [PATCH 18/19] Ajout du code de suivi Matomo --- src/app.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/app.py b/src/app.py index a88fc54..878302a 100644 --- a/src/app.py +++ b/src/app.py @@ -4,6 +4,36 @@ import dash_bootstrap_components as dbc app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info", use_pages=True) +app.index_string = """ + + + + {%metas%} + {%title%} + {%favicon%} + {%css%} + + + {%app_entry%} +
+ {%config%} + {%scripts%} + {%renderer%} +
+